• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 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 
17 package com.android.server.display;
18 
19 import static org.junit.Assert.assertArrayEquals;
20 import static org.junit.Assert.assertEquals;
21 import static org.junit.Assert.assertFalse;
22 import static org.junit.Assert.assertNotNull;
23 import static org.junit.Assert.assertNull;
24 import static org.junit.Assert.assertTrue;
25 import static org.junit.Assert.fail;
26 
27 import android.app.ActivityTaskManager.RootTaskInfo;
28 import android.content.BroadcastReceiver;
29 import android.content.ComponentName;
30 import android.content.ContentResolver;
31 import android.content.Context;
32 import android.content.Intent;
33 import android.content.IntentFilter;
34 import android.content.pm.ParceledListSlice;
35 import android.database.ContentObserver;
36 import android.hardware.SensorEvent;
37 import android.hardware.SensorEventListener;
38 import android.hardware.display.AmbientBrightnessDayStats;
39 import android.hardware.display.BrightnessChangeEvent;
40 import android.hardware.display.BrightnessConfiguration;
41 import android.hardware.display.ColorDisplayManager;
42 import android.hardware.display.DisplayManager;
43 import android.hardware.display.DisplayedContentSample;
44 import android.hardware.display.DisplayedContentSamplingAttributes;
45 import android.os.BatteryManager;
46 import android.os.Handler;
47 import android.os.HandlerThread;
48 import android.os.MessageQueue;
49 import android.os.Parcel;
50 import android.os.RemoteException;
51 import android.os.SystemClock;
52 import android.os.UserManager;
53 import android.provider.Settings;
54 import android.util.AtomicFile;
55 import android.view.Display;
56 
57 import androidx.test.InstrumentationRegistry;
58 import androidx.test.filters.SmallTest;
59 import androidx.test.runner.AndroidJUnit4;
60 
61 import com.android.internal.R;
62 
63 import org.junit.Before;
64 import org.junit.Test;
65 import org.junit.runner.RunWith;
66 
67 import java.io.ByteArrayInputStream;
68 import java.io.ByteArrayOutputStream;
69 import java.io.IOException;
70 import java.io.InputStream;
71 import java.lang.reflect.Constructor;
72 import java.nio.charset.StandardCharsets;
73 import java.util.HashMap;
74 import java.util.List;
75 import java.util.Map;
76 import java.util.concurrent.CountDownLatch;
77 import java.util.concurrent.TimeUnit;
78 
79 @SmallTest
80 @RunWith(AndroidJUnit4.class)
81 public class BrightnessTrackerTest {
82     private static final float DEFAULT_INITIAL_BRIGHTNESS = 2.5f;
83     private static final boolean DEFAULT_COLOR_SAMPLING_ENABLED = true;
84     private static final String DEFAULT_DISPLAY_ID = "123";
85     private static final float FLOAT_DELTA = 0.01f;
86 
87     private BrightnessTracker mTracker;
88     private TestInjector mInjector;
89 
90     private static Object sHandlerLock = new Object();
91     private static Handler sHandler;
92     private static HandlerThread sThread =
93             new HandlerThread("brightness.test", android.os.Process.THREAD_PRIORITY_BACKGROUND);
94 
95     private int mDefaultNightModeColorTemperature;
96     private float mRbcOffsetFactor;
97 
ensureHandler()98     private static Handler ensureHandler() {
99         synchronized (sHandlerLock) {
100             if (sHandler == null) {
101                 sThread.start();
102                 sHandler = new Handler(sThread.getLooper());
103             }
104             return sHandler;
105         }
106     }
107 
108 
109     @Before
setUp()110     public void setUp() throws Exception {
111         mInjector = new TestInjector(ensureHandler());
112 
113         mTracker = new BrightnessTracker(InstrumentationRegistry.getContext(), mInjector);
114         mDefaultNightModeColorTemperature =
115                 InstrumentationRegistry.getContext().getResources().getInteger(
116                 R.integer.config_nightDisplayColorTemperatureDefault);
117         mRbcOffsetFactor = InstrumentationRegistry.getContext()
118                 .getSystemService(ColorDisplayManager.class).getReduceBrightColorsOffsetFactor();
119     }
120 
121     @Test
testStartStopTrackerScreenOnOff()122     public void testStartStopTrackerScreenOnOff() {
123         mInjector.mInteractive = false;
124         startTracker(mTracker);
125         assertNull(mInjector.mSensorListener);
126         assertNotNull(mInjector.mBroadcastReceiver);
127         assertTrue(mInjector.mIdleScheduled);
128         mInjector.sendScreenChange(/*screen on */ true);
129         assertNotNull(mInjector.mSensorListener);
130         assertTrue(mInjector.mColorSamplingEnabled);
131 
132         mInjector.sendScreenChange(/*screen on */ false);
133         assertNull(mInjector.mSensorListener);
134         assertFalse(mInjector.mColorSamplingEnabled);
135 
136         // Turn screen on while brightness mode is manual
137         mInjector.setBrightnessMode(/* isBrightnessModeAutomatic */ false);
138         mInjector.sendScreenChange(/*screen on */ true);
139         assertNull(mInjector.mSensorListener);
140         assertFalse(mInjector.mColorSamplingEnabled);
141 
142         // Set brightness mode to automatic while screen is off.
143         mInjector.sendScreenChange(/*screen on */ false);
144         mInjector.setBrightnessMode(/* isBrightnessModeAutomatic */ true);
145         assertNull(mInjector.mSensorListener);
146         assertFalse(mInjector.mColorSamplingEnabled);
147 
148         // Turn on screen while brightness mode is automatic.
149         mInjector.sendScreenChange(/*screen on */ true);
150         assertNotNull(mInjector.mSensorListener);
151         assertTrue(mInjector.mColorSamplingEnabled);
152 
153         mTracker.stop();
154         assertNull(mInjector.mSensorListener);
155         assertNull(mInjector.mBroadcastReceiver);
156         assertFalse(mInjector.mIdleScheduled);
157         assertFalse(mInjector.mColorSamplingEnabled);
158     }
159 
160     @Test
testModifyBrightnessConfiguration()161     public void testModifyBrightnessConfiguration() {
162         mInjector.mInteractive = true;
163         // Start with tracker not listening for color samples.
164         startTracker(mTracker, DEFAULT_INITIAL_BRIGHTNESS, /* collectColorSamples= */ false);
165         assertFalse(mInjector.mColorSamplingEnabled);
166 
167         // Update brightness config to enabled color sampling.
168         mTracker.setBrightnessConfiguration(buildBrightnessConfiguration(
169                 /* collectColorSamples= */ true));
170         mInjector.waitForHandler();
171         assertTrue(mInjector.mColorSamplingEnabled);
172 
173         // Update brightness config to disable color sampling.
174         mTracker.setBrightnessConfiguration(buildBrightnessConfiguration(
175                 /* collectColorSamples= */ false));
176         mInjector.waitForHandler();
177         assertFalse(mInjector.mColorSamplingEnabled);
178 
179         // Pretend screen is off, update config to turn on color sampling.
180         mInjector.sendScreenChange(/*screen on */ false);
181         mTracker.setBrightnessConfiguration(buildBrightnessConfiguration(
182                 /* collectColorSamples= */ true));
183         mInjector.waitForHandler();
184         assertFalse(mInjector.mColorSamplingEnabled);
185 
186         // Pretend screen is on.
187         mInjector.sendScreenChange(/*screen on */ true);
188         assertTrue(mInjector.mColorSamplingEnabled);
189 
190         mTracker.stop();
191         assertFalse(mInjector.mColorSamplingEnabled);
192     }
193 
194     @Test
testNoColorSampling_WrongPixelFormat()195     public void testNoColorSampling_WrongPixelFormat() {
196         mInjector.mDefaultSamplingAttributes =
197                 new DisplayedContentSamplingAttributes(
198                         0x23,
199                         mInjector.mDefaultSamplingAttributes.getDataspace(),
200                         mInjector.mDefaultSamplingAttributes.getComponentMask());
201         startTracker(mTracker);
202         assertFalse(mInjector.mColorSamplingEnabled);
203         assertNull(mInjector.mDisplayListener);
204     }
205 
206     @Test
testNoColorSampling_MissingComponent()207     public void testNoColorSampling_MissingComponent() {
208         mInjector.mDefaultSamplingAttributes =
209                 new DisplayedContentSamplingAttributes(
210                         mInjector.mDefaultSamplingAttributes.getPixelFormat(),
211                         mInjector.mDefaultSamplingAttributes.getDataspace(),
212                         0x2);
213         startTracker(mTracker);
214         assertFalse(mInjector.mColorSamplingEnabled);
215         assertNull(mInjector.mDisplayListener);
216     }
217 
218     @Test
testNoColorSampling_NoSupport()219     public void testNoColorSampling_NoSupport() {
220         mInjector.mDefaultSamplingAttributes = null;
221         startTracker(mTracker);
222         assertFalse(mInjector.mColorSamplingEnabled);
223         assertNull(mInjector.mDisplayListener);
224     }
225 
226     @Test
testColorSampling_FrameRateChange()227     public void testColorSampling_FrameRateChange() {
228         startTracker(mTracker);
229         assertTrue(mInjector.mColorSamplingEnabled);
230         assertNotNull(mInjector.mDisplayListener);
231         int noFramesSampled = mInjector.mNoColorSamplingFrames;
232         mInjector.mFrameRate = 120.0f;
233         // Wrong display
234         mInjector.mDisplayListener.onDisplayChanged(Display.DEFAULT_DISPLAY + 10);
235         assertEquals(noFramesSampled, mInjector.mNoColorSamplingFrames);
236         // Correct display
237         mInjector.mDisplayListener.onDisplayChanged(Display.DEFAULT_DISPLAY);
238         assertEquals(noFramesSampled * 2, mInjector.mNoColorSamplingFrames);
239     }
240 
241     @Test
testAdaptiveOnOff()242     public void testAdaptiveOnOff() {
243         mInjector.mInteractive = true;
244         mInjector.mIsBrightnessModeAutomatic = false;
245         startTracker(mTracker);
246         assertNull(mInjector.mSensorListener);
247         assertNotNull(mInjector.mBroadcastReceiver);
248         assertNotNull(mInjector.mContentObserver);
249         assertTrue(mInjector.mIdleScheduled);
250         assertFalse(mInjector.mColorSamplingEnabled);
251         assertNull(mInjector.mDisplayListener);
252 
253         mInjector.setBrightnessMode(/*isBrightnessModeAutomatic*/ true);
254         assertNotNull(mInjector.mSensorListener);
255         assertTrue(mInjector.mColorSamplingEnabled);
256         assertNotNull(mInjector.mDisplayListener);
257 
258         SensorEventListener listener = mInjector.mSensorListener;
259         DisplayManager.DisplayListener displayListener = mInjector.mDisplayListener;
260         mInjector.mSensorListener = null;
261         mInjector.mColorSamplingEnabled = false;
262         mInjector.mDisplayListener = null;
263         // Duplicate notification
264         mInjector.setBrightnessMode(/*isBrightnessModeAutomatic*/ true);
265         // Sensor shouldn't have been registered as it was already registered.
266         assertNull(mInjector.mSensorListener);
267         assertFalse(mInjector.mColorSamplingEnabled);
268         assertNull(mInjector.mDisplayListener);
269         mInjector.mSensorListener = listener;
270         mInjector.mDisplayListener = displayListener;
271         mInjector.mColorSamplingEnabled = true;
272 
273         mInjector.setBrightnessMode(/*isBrightnessModeAutomatic*/ false);
274         assertNull(mInjector.mSensorListener);
275         assertFalse(mInjector.mColorSamplingEnabled);
276         assertNull(mInjector.mDisplayListener);
277 
278         mTracker.stop();
279         assertNull(mInjector.mSensorListener);
280         assertNull(mInjector.mBroadcastReceiver);
281         assertNull(mInjector.mContentObserver);
282         assertFalse(mInjector.mIdleScheduled);
283         assertFalse(mInjector.mColorSamplingEnabled);
284         assertNull(mInjector.mDisplayListener);
285     }
286 
287     @Test
testBrightnessEvent()288     public void testBrightnessEvent() {
289         final float brightness = 0.5f;
290         final String displayId = "1234";
291 
292         startTracker(mTracker);
293         mInjector.mSensorListener.onSensorChanged(createSensorEvent(1.0f));
294         mInjector.incrementTime(TimeUnit.SECONDS.toMillis(2));
295         notifyBrightnessChanged(mTracker, brightness, displayId);
296         List<BrightnessChangeEvent> events = mTracker.getEvents(0, true).getList();
297         mTracker.stop();
298 
299         assertEquals(1, events.size());
300         BrightnessChangeEvent event = events.get(0);
301         assertEquals(mInjector.currentTimeMillis(), event.timeStamp);
302         assertEquals(displayId, event.uniqueDisplayId);
303         assertEquals(1, event.luxValues.length);
304         assertEquals(1.0f, event.luxValues[0], FLOAT_DELTA);
305         assertEquals(mInjector.currentTimeMillis() - TimeUnit.SECONDS.toMillis(2),
306                 event.luxTimestamps[0]);
307         assertEquals(brightness, event.brightness, FLOAT_DELTA);
308         assertEquals(DEFAULT_INITIAL_BRIGHTNESS, event.lastBrightness, FLOAT_DELTA);
309 
310         // System had no data so these should all be at defaults.
311         assertEquals(Float.NaN, event.batteryLevel, 0.0);
312         assertFalse(event.nightMode);
313         assertEquals(mDefaultNightModeColorTemperature, event.colorTemperature);
314     }
315 
316     @Test
testBrightnessFullPopulatedEvent()317     public void testBrightnessFullPopulatedEvent() {
318         final int initialBrightness = 230;
319         final int brightness = 130;
320         final String displayId = "1234";
321 
322         mInjector.mSecureIntSettings.put(Settings.Secure.NIGHT_DISPLAY_ACTIVATED, 1);
323         mInjector.mSecureIntSettings.put(Settings.Secure.NIGHT_DISPLAY_COLOR_TEMPERATURE, 3333);
324 
325         mInjector.mSecureIntSettings.put(Settings.Secure.REDUCE_BRIGHT_COLORS_ACTIVATED, 1);
326         mInjector.mSecureIntSettings.put(Settings.Secure.REDUCE_BRIGHT_COLORS_LEVEL, 40);
327 
328         startTracker(mTracker, initialBrightness, DEFAULT_COLOR_SAMPLING_ENABLED);
329         mInjector.mBroadcastReceiver.onReceive(InstrumentationRegistry.getContext(),
330                 batteryChangeEvent(30, 60));
331         mInjector.mSensorListener.onSensorChanged(createSensorEvent(1000.0f));
332         final long sensorTime = mInjector.currentTimeMillis();
333         notifyBrightnessChanged(mTracker, brightness, displayId);
334         List<BrightnessChangeEvent> eventsNoPackage
335                 = mTracker.getEvents(0, false).getList();
336         List<BrightnessChangeEvent> events = mTracker.getEvents(0, true).getList();
337         mTracker.stop();
338 
339         assertEquals(1, events.size());
340         BrightnessChangeEvent event = events.get(0);
341         assertEquals(event.timeStamp, mInjector.currentTimeMillis());
342         assertEquals(displayId, event.uniqueDisplayId);
343         assertArrayEquals(new float[] {1000.0f}, event.luxValues, 0.01f);
344         assertArrayEquals(new long[] {sensorTime}, event.luxTimestamps);
345         assertEquals(brightness, event.brightness, FLOAT_DELTA);
346         assertEquals(initialBrightness, event.lastBrightness, FLOAT_DELTA);
347         assertEquals(0.5, event.batteryLevel, FLOAT_DELTA);
348         assertTrue(event.nightMode);
349         assertEquals(3333, event.colorTemperature);
350         assertTrue(event.reduceBrightColors);
351         assertEquals(40, event.reduceBrightColorsStrength);
352         assertEquals(brightness * mRbcOffsetFactor, event.reduceBrightColorsOffset, FLOAT_DELTA);
353         assertEquals("a.package", event.packageName);
354         assertEquals(0, event.userId);
355         assertArrayEquals(new long[] {1, 10, 100, 1000, 300, 30, 10, 1}, event.colorValueBuckets);
356         assertEquals(10000, event.colorSampleDuration);
357 
358         assertEquals(1, eventsNoPackage.size());
359         assertNull(eventsNoPackage.get(0).packageName);
360     }
361 
362     @Test
testIgnoreAutomaticBrightnessChange()363     public void testIgnoreAutomaticBrightnessChange() {
364         final int initialBrightness = 30;
365         startTracker(mTracker, initialBrightness, DEFAULT_COLOR_SAMPLING_ENABLED);
366         mInjector.mSensorListener.onSensorChanged(createSensorEvent(1.0f));
367         mInjector.incrementTime(TimeUnit.SECONDS.toMillis(1));
368 
369         final int systemUpdatedBrightness = 20;
370         notifyBrightnessChanged(mTracker, systemUpdatedBrightness, false /*userInitiated*/,
371                 0.5f /*powerBrightnessFactor(*/, false /*isUserSetBrightness*/,
372                 false /*isDefaultBrightnessConfig*/, DEFAULT_DISPLAY_ID);
373         List<BrightnessChangeEvent> events = mTracker.getEvents(0, true).getList();
374         // No events because we filtered out our change.
375         assertEquals(0, events.size());
376 
377         final int firstUserUpdateBrightness = 20;
378         // Then change comes from somewhere else so we shouldn't filter.
379         notifyBrightnessChanged(mTracker, firstUserUpdateBrightness);
380 
381         // and with a different brightness value.
382         final int secondUserUpdateBrightness = 34;
383         notifyBrightnessChanged(mTracker, secondUserUpdateBrightness);
384         events = mTracker.getEvents(0, true).getList();
385 
386         assertEquals(2, events.size());
387         // First event is change from system update (20) to first user update (20)
388         assertEquals(systemUpdatedBrightness, events.get(0).lastBrightness, FLOAT_DELTA);
389         assertEquals(firstUserUpdateBrightness, events.get(0).brightness, FLOAT_DELTA);
390         // Second event is from first to second user update.
391         assertEquals(firstUserUpdateBrightness, events.get(1).lastBrightness, FLOAT_DELTA);
392         assertEquals(secondUserUpdateBrightness, events.get(1).brightness, FLOAT_DELTA);
393 
394         mTracker.stop();
395     }
396 
397     @Test
testLimitedBufferSize()398     public void testLimitedBufferSize() {
399         startTracker(mTracker);
400         mInjector.mSensorListener.onSensorChanged(createSensorEvent(1.0f));
401 
402         for (int brightness = 0; brightness <= 255; ++brightness) {
403             mInjector.mSensorListener.onSensorChanged(createSensorEvent(1.0f));
404             mInjector.incrementTime(TimeUnit.SECONDS.toNanos(1));
405             notifyBrightnessChanged(mTracker, brightness);
406         }
407         List<BrightnessChangeEvent> events = mTracker.getEvents(0, true).getList();
408         mTracker.stop();
409 
410         // Should be capped at 100 events, and they should be the most recent 100.
411         assertEquals(100, events.size());
412         for (int i = 0; i < events.size(); i++) {
413             BrightnessChangeEvent event = events.get(i);
414             assertEquals(156 + i, event.brightness, FLOAT_DELTA);
415         }
416     }
417 
418     @Test
testLimitedSensorEvents()419     public void testLimitedSensorEvents() {
420         final int brightness = 20;
421 
422         startTracker(mTracker);
423         // 20 Sensor events 1 second apart.
424         for (int i = 0; i < 20; ++i) {
425             mInjector.incrementTime(TimeUnit.SECONDS.toMillis(1));
426             mInjector.mSensorListener.onSensorChanged(createSensorEvent(i + 1.0f));
427         }
428         notifyBrightnessChanged(mTracker, 20);
429         List<BrightnessChangeEvent> events = mTracker.getEvents(0, true).getList();
430         mTracker.stop();
431 
432         assertEquals(1, events.size());
433         BrightnessChangeEvent event = events.get(0);
434         assertEquals(mInjector.currentTimeMillis(), event.timeStamp);
435 
436         // 12 sensor events, 11 for 0->10 seconds + 1 previous event.
437         assertEquals(12, event.luxValues.length);
438         for (int i = 0; i < 12; ++i) {
439             assertEquals(event.luxTimestamps[11 - i],
440                     mInjector.currentTimeMillis() - i * TimeUnit.SECONDS.toMillis(1));
441         }
442         assertEquals(brightness, event.brightness, FLOAT_DELTA);
443     }
444 
445     @Test
testReadEvents()446     public void testReadEvents() throws Exception {
447         BrightnessTracker tracker = new BrightnessTracker(InstrumentationRegistry.getContext(),
448                 mInjector);
449         mInjector.mCurrentTimeMillis = System.currentTimeMillis();
450         long someTimeAgo = System.currentTimeMillis() - TimeUnit.HOURS.toMillis(12);
451         long twoMonthsAgo = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(60);
452         // 3 Events in the file but one too old to read.
453         String eventFile =
454                 "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
455                 + "<events>\n"
456                 + "<event nits=\"194.2\" timestamp=\""
457                 + Long.toString(someTimeAgo) + "\" packageName=\""
458                 + "com.example.app\" user=\"10\" "
459                 + "lastNits=\"32.333\" "
460                 + "batteryLevel=\"1.0\" nightMode=\"false\" colorTemperature=\"0\" "
461                 + "reduceBrightColors=\"false\" reduceBrightColorsStrength=\"40\" "
462                 + "reduceBrightColorsOffset=\"0\"\n"
463                 + "uniqueDisplayId=\"123\""
464                 + "lux=\"32.2,31.1\" luxTimestamps=\""
465                 + Long.toString(someTimeAgo) + "," + Long.toString(someTimeAgo) + "\""
466                 + "defaultConfig=\"true\" powerSaveFactor=\"0.5\" userPoint=\"true\" />"
467                 + "<event nits=\"71\" timestamp=\""
468                 + Long.toString(someTimeAgo) + "\" packageName=\""
469                 + "com.android.anapp\" user=\"11\" "
470                 + "lastNits=\"32\" "
471                 + "batteryLevel=\"0.5\" nightMode=\"true\" colorTemperature=\"3235\" "
472                 + "reduceBrightColors=\"true\" reduceBrightColorsStrength=\"40\" "
473                 + "reduceBrightColorsOffset=\"0\"\n"
474                 + "uniqueDisplayId=\"456\""
475                 + "lux=\"132.2,131.1\" luxTimestamps=\""
476                 + Long.toString(someTimeAgo) + "," + Long.toString(someTimeAgo) + "\""
477                 + "colorSampleDuration=\"3456\" colorValueBuckets=\"123,598,23,19\"/>"
478                 // Event that is too old so shouldn't show up.
479                 + "<event nits=\"142\" timestamp=\""
480                 + Long.toString(twoMonthsAgo) + "\" packageName=\""
481                 + "com.example.app\" user=\"10\" "
482                 + "lastNits=\"32\" "
483                 + "batteryLevel=\"1.0\" nightMode=\"false\" colorTemperature=\"0\" "
484                 + "reduceBrightColors=\"false\" reduceBrightColorsStrength=\"40\" "
485                 + "reduceBrightColorsOffset=\"0\"\n"
486                 + "uniqueDisplayId=\"789\""
487                 + "lux=\"32.2,31.1\" luxTimestamps=\""
488                 + Long.toString(twoMonthsAgo) + "," + Long.toString(twoMonthsAgo) + "\"/>"
489                 + "</events>";
490         tracker.readEventsLocked(getInputStream(eventFile));
491         List<BrightnessChangeEvent> events = tracker.getEvents(0, true).getList();
492         assertEquals(1, events.size());
493         BrightnessChangeEvent event = events.get(0);
494         assertEquals(someTimeAgo, event.timeStamp);
495         assertEquals(194.2, event.brightness, FLOAT_DELTA);
496         assertEquals("123", event.uniqueDisplayId);
497         assertArrayEquals(new float[] {32.2f, 31.1f}, event.luxValues, FLOAT_DELTA);
498         assertArrayEquals(new long[] {someTimeAgo, someTimeAgo}, event.luxTimestamps);
499         assertEquals(32.333, event.lastBrightness, FLOAT_DELTA);
500         assertEquals(0, event.userId);
501         assertFalse(event.nightMode);
502         assertFalse(event.reduceBrightColors);
503         assertEquals(1.0f, event.batteryLevel, FLOAT_DELTA);
504         assertEquals("com.example.app", event.packageName);
505         assertTrue(event.isDefaultBrightnessConfig);
506         assertEquals(0.5f, event.powerBrightnessFactor, FLOAT_DELTA);
507         assertTrue(event.isUserSetBrightness);
508         assertNull(event.colorValueBuckets);
509 
510         events = tracker.getEvents(1, true).getList();
511         assertEquals(1, events.size());
512         event = events.get(0);
513         assertEquals(someTimeAgo, event.timeStamp);
514         assertEquals(71, event.brightness, FLOAT_DELTA);
515         assertEquals("456", event.uniqueDisplayId);
516         assertArrayEquals(new float[] {132.2f, 131.1f}, event.luxValues, FLOAT_DELTA);
517         assertArrayEquals(new long[] {someTimeAgo, someTimeAgo}, event.luxTimestamps);
518         assertEquals(32, event.lastBrightness, FLOAT_DELTA);
519         assertEquals(1, event.userId);
520         assertTrue(event.nightMode);
521         assertEquals(3235, event.colorTemperature);
522         assertTrue(event.reduceBrightColors);
523         assertEquals(0.5f, event.batteryLevel, FLOAT_DELTA);
524         assertEquals("com.android.anapp", event.packageName);
525         // Not present in the event so default to false.
526         assertFalse(event.isDefaultBrightnessConfig);
527         assertEquals(1.0, event.powerBrightnessFactor, FLOAT_DELTA);
528         assertFalse(event.isUserSetBrightness);
529         assertEquals(3456L, event.colorSampleDuration);
530         assertArrayEquals(new long[] {123L, 598L, 23L, 19L}, event.colorValueBuckets);
531 
532         // Pretend user 1 is a profile of user 0.
533         mInjector.mProfiles = new int[]{0, 1};
534         events = tracker.getEvents(0, true).getList();
535         // Both events should now be returned.
536         assertEquals(2, events.size());
537         BrightnessChangeEvent userZeroEvent;
538         BrightnessChangeEvent userOneEvent;
539         if (events.get(0).userId == 0) {
540             userZeroEvent = events.get(0);
541             userOneEvent = events.get(1);
542         } else {
543             userZeroEvent = events.get(1);
544             userOneEvent = events.get(0);
545         }
546         assertEquals(0, userZeroEvent.userId);
547         assertEquals("com.example.app", userZeroEvent.packageName);
548         assertEquals(1, userOneEvent.userId);
549         // Events from user 1 should have the package name redacted
550         assertNull(userOneEvent.packageName);
551     }
552 
553     @Test
testFailedRead()554     public void testFailedRead() {
555         String someTimeAgo =
556                 Long.toString(System.currentTimeMillis() - TimeUnit.HOURS.toMillis(12));
557         mInjector.mCurrentTimeMillis = System.currentTimeMillis();
558 
559         BrightnessTracker tracker = new BrightnessTracker(InstrumentationRegistry.getContext(),
560                 mInjector);
561         String eventFile = "junk in the file";
562         try {
563             tracker.readEventsLocked(getInputStream(eventFile));
564         } catch (IOException e) {
565             // Expected;
566         }
567         assertEquals(0, tracker.getEvents(0, true).getList().size());
568 
569         // Missing lux value.
570         eventFile =
571                 "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
572                         + "<events>\n"
573                         + "<event nits=\"194\" timestamp=\"" + someTimeAgo + "\" packageName=\""
574                         + "com.example.app\" user=\"10\" "
575                         + "batteryLevel=\"0.7\" nightMode=\"false\" colorTemperature=\"0\" />\n"
576                         + "</events>";
577         try {
578             tracker.readEventsLocked(getInputStream(eventFile));
579         } catch (IOException e) {
580             // Expected;
581         }
582         assertEquals(0, tracker.getEvents(0, true).getList().size());
583     }
584 
585     @Test
testWriteThenRead()586     public void testWriteThenRead() throws Exception {
587         final int brightness = 20;
588         final String displayId = "1234";
589 
590         mInjector.mSecureIntSettings.put(Settings.Secure.NIGHT_DISPLAY_ACTIVATED, 1);
591         mInjector.mSecureIntSettings.put(Settings.Secure.NIGHT_DISPLAY_COLOR_TEMPERATURE, 3339);
592 
593         mInjector.mSecureIntSettings.put(Settings.Secure.REDUCE_BRIGHT_COLORS_ACTIVATED, 1);
594         mInjector.mSecureIntSettings.put(Settings.Secure.REDUCE_BRIGHT_COLORS_LEVEL, 40);
595 
596         startTracker(mTracker);
597         mInjector.mBroadcastReceiver.onReceive(InstrumentationRegistry.getContext(),
598                 batteryChangeEvent(30, 100));
599         mInjector.mSensorListener.onSensorChanged(createSensorEvent(2000.0f));
600         final long firstSensorTime = mInjector.currentTimeMillis();
601         mInjector.incrementTime(TimeUnit.SECONDS.toMillis(2));
602         mInjector.mSensorListener.onSensorChanged(createSensorEvent(3000.0f));
603         final long secondSensorTime = mInjector.currentTimeMillis();
604         mInjector.incrementTime(TimeUnit.SECONDS.toMillis(3));
605         notifyBrightnessChanged(mTracker, brightness, true /*userInitiated*/,
606                 0.5f /*powerBrightnessFactor*/, true /*hasUserBrightnessPoints*/,
607                 false /*isDefaultBrightnessConfig*/, displayId);
608         ByteArrayOutputStream baos = new ByteArrayOutputStream();
609         mTracker.writeEventsLocked(baos);
610         mTracker.stop();
611 
612         baos.flush();
613         ByteArrayInputStream input = new ByteArrayInputStream(baos.toByteArray());
614         BrightnessTracker tracker = new BrightnessTracker(InstrumentationRegistry.getContext(),
615                 mInjector);
616         tracker.readEventsLocked(input);
617         List<BrightnessChangeEvent> events = tracker.getEvents(0, true).getList();
618 
619         assertEquals(1, events.size());
620         BrightnessChangeEvent event = events.get(0);
621         assertEquals(displayId, event.uniqueDisplayId);
622         assertArrayEquals(new float[] {2000.0f, 3000.0f}, event.luxValues, FLOAT_DELTA);
623         assertArrayEquals(new long[] {firstSensorTime, secondSensorTime}, event.luxTimestamps);
624         assertEquals(brightness, event.brightness, FLOAT_DELTA);
625         assertEquals(0.3, event.batteryLevel, FLOAT_DELTA);
626         assertTrue(event.nightMode);
627         assertEquals(3339, event.colorTemperature);
628         assertTrue(event.reduceBrightColors);
629         assertEquals(40, event.reduceBrightColorsStrength);
630         assertEquals(brightness * mRbcOffsetFactor, event.reduceBrightColorsOffset, FLOAT_DELTA);
631         assertEquals(0.5f, event.powerBrightnessFactor, FLOAT_DELTA);
632         assertTrue(event.isUserSetBrightness);
633         assertFalse(event.isDefaultBrightnessConfig);
634         assertArrayEquals(new long[] {1, 10, 100, 1000, 300, 30, 10, 1}, event.colorValueBuckets);
635         assertEquals(10000, event.colorSampleDuration);
636     }
637 
638     @Test
testWritePrunesOldEvents()639     public void testWritePrunesOldEvents() throws Exception {
640         final int brightness = 20;
641 
642         mInjector.mSecureIntSettings.put(Settings.Secure.NIGHT_DISPLAY_ACTIVATED, 1);
643         mInjector.mSecureIntSettings.put(Settings.Secure.NIGHT_DISPLAY_COLOR_TEMPERATURE, 3339);
644 
645         mInjector.mSecureIntSettings.put(Settings.Secure.REDUCE_BRIGHT_COLORS_ACTIVATED, 1);
646         mInjector.mSecureIntSettings.put(Settings.Secure.REDUCE_BRIGHT_COLORS_LEVEL, 40);
647 
648         startTracker(mTracker);
649         mInjector.mBroadcastReceiver.onReceive(InstrumentationRegistry.getContext(),
650                 batteryChangeEvent(30, 100));
651         mInjector.mSensorListener.onSensorChanged(createSensorEvent(1000.0f));
652         mInjector.incrementTime(TimeUnit.SECONDS.toMillis(1));
653         mInjector.mSensorListener.onSensorChanged(createSensorEvent(2000.0f));
654         final long sensorTime = mInjector.currentTimeMillis();
655         notifyBrightnessChanged(mTracker, brightness);
656 
657         // 31 days later
658         mInjector.incrementTime(TimeUnit.DAYS.toMillis(31));
659         mInjector.mSensorListener.onSensorChanged(createSensorEvent(3000.0f));
660         notifyBrightnessChanged(mTracker, brightness);
661         final long eventTime = mInjector.currentTimeMillis();
662 
663         List<BrightnessChangeEvent> events = mTracker.getEvents(0, true).getList();
664         assertEquals(2, events.size());
665 
666         ByteArrayOutputStream baos = new ByteArrayOutputStream();
667         mTracker.writeEventsLocked(baos);
668         events = mTracker.getEvents(0, true).getList();
669         mTracker.stop();
670 
671         assertEquals(1, events.size());
672         BrightnessChangeEvent event = events.get(0);
673         assertEquals(eventTime, event.timeStamp);
674 
675         // We will keep one of the old sensor events because we keep 1 event outside the window.
676         assertArrayEquals(new float[] {2000.0f, 3000.0f}, event.luxValues, FLOAT_DELTA);
677         assertArrayEquals(new long[] {sensorTime, eventTime}, event.luxTimestamps);
678         assertEquals(brightness, event.brightness, FLOAT_DELTA);
679         assertEquals(0.3, event.batteryLevel, FLOAT_DELTA);
680         assertTrue(event.nightMode);
681         assertTrue(event.reduceBrightColors);
682         assertEquals(3339, event.colorTemperature);
683     }
684 
685     @Test
testParcelUnParcel()686     public void testParcelUnParcel() {
687         Parcel parcel = Parcel.obtain();
688         BrightnessChangeEvent.Builder builder = new BrightnessChangeEvent.Builder();
689         builder.setBrightness(23f);
690         builder.setTimeStamp(345L);
691         builder.setPackageName("com.example");
692         builder.setUserId(12);
693         builder.setUniqueDisplayId("9876");
694         float[] luxValues = new float[2];
695         luxValues[0] = 3000.0f;
696         luxValues[1] = 4000.0f;
697         builder.setLuxValues(luxValues);
698         long[] luxTimestamps = new long[2];
699         luxTimestamps[0] = 325L;
700         luxTimestamps[1] = 315L;
701         builder.setLuxTimestamps(luxTimestamps);
702         builder.setBatteryLevel(0.7f);
703         builder.setNightMode(false);
704         builder.setColorTemperature(345);
705         builder.setReduceBrightColors(false);
706         builder.setReduceBrightColorsStrength(40);
707         builder.setReduceBrightColorsOffset(20f);
708         builder.setLastBrightness(50f);
709         builder.setColorValues(new long[] {23, 34, 45}, 1000L);
710         BrightnessChangeEvent event = builder.build();
711 
712         event.writeToParcel(parcel, 0);
713         byte[] parceled = parcel.marshall();
714         parcel.recycle();
715 
716         parcel = Parcel.obtain();
717         parcel.unmarshall(parceled, 0, parceled.length);
718         parcel.setDataPosition(0);
719 
720         BrightnessChangeEvent event2 = BrightnessChangeEvent.CREATOR.createFromParcel(parcel);
721         parcel.recycle();
722         assertEquals(event.brightness, event2.brightness, FLOAT_DELTA);
723         assertEquals(event.timeStamp, event2.timeStamp);
724         assertEquals(event.packageName, event2.packageName);
725         assertEquals(event.userId, event2.userId);
726         assertEquals(event.uniqueDisplayId, event2.uniqueDisplayId);
727         assertArrayEquals(event.luxValues, event2.luxValues, FLOAT_DELTA);
728         assertArrayEquals(event.luxTimestamps, event2.luxTimestamps);
729         assertEquals(event.batteryLevel, event2.batteryLevel, FLOAT_DELTA);
730         assertEquals(event.nightMode, event2.nightMode);
731         assertEquals(event.colorTemperature, event2.colorTemperature);
732         assertEquals(event.reduceBrightColors, event2.reduceBrightColors);
733         assertEquals(event.reduceBrightColorsStrength, event2.reduceBrightColorsStrength);
734         assertEquals(event.reduceBrightColorsOffset, event2.reduceBrightColorsOffset, FLOAT_DELTA);
735         assertEquals(event.lastBrightness, event2.lastBrightness, FLOAT_DELTA);
736         assertArrayEquals(event.colorValueBuckets, event2.colorValueBuckets);
737         assertEquals(event.colorSampleDuration, event2.colorSampleDuration);
738 
739         parcel = Parcel.obtain();
740         builder.setBatteryLevel(Float.NaN);
741         event = builder.build();
742         event.writeToParcel(parcel, 0);
743         parceled = parcel.marshall();
744         parcel.recycle();
745 
746         parcel = Parcel.obtain();
747         parcel.unmarshall(parceled, 0, parceled.length);
748         parcel.setDataPosition(0);
749         event2 = BrightnessChangeEvent.CREATOR.createFromParcel(parcel);
750         assertEquals(event.batteryLevel, event2.batteryLevel, FLOAT_DELTA);
751     }
752 
753     @Test
testNonNullAmbientStats()754     public void testNonNullAmbientStats() {
755         // getAmbientBrightnessStats should return an empty list rather than null when
756         // tracker isn't started or hasn't collected any data.
757         ParceledListSlice<AmbientBrightnessDayStats> slice = mTracker.getAmbientBrightnessStats(0);
758         assertNotNull(slice);
759         assertTrue(slice.getList().isEmpty());
760         startTracker(mTracker);
761         slice = mTracker.getAmbientBrightnessStats(0);
762         assertNotNull(slice);
763         assertTrue(slice.getList().isEmpty());
764     }
765 
766     @Test
testBackgroundHandlerDelay()767     public void testBackgroundHandlerDelay() {
768         final int brightness = 20;
769 
770         // Setup tracker.
771         startTracker(mTracker);
772         mInjector.mSensorListener.onSensorChanged(createSensorEvent(1.0f));
773         mInjector.incrementTime(TimeUnit.SECONDS.toMillis(2));
774 
775         // Block handler from running.
776         final CountDownLatch latch = new CountDownLatch(1);
777         mInjector.mHandler.post(
778                 () -> {
779                     try {
780                         latch.await();
781                     } catch (InterruptedException e) {
782                         fail(e.getMessage());
783                     }
784                 });
785 
786         // Send an event.
787         long eventTime = mInjector.currentTimeMillis();
788         mTracker.notifyBrightnessChanged(brightness, true /*userInitiated*/,
789                 1.0f /*powerBrightnessFactor*/, false /*isUserSetBrightness*/,
790                 false /*isDefaultBrightnessConfig*/, DEFAULT_DISPLAY_ID);
791 
792         // Time passes before handler can run.
793         mInjector.incrementTime(TimeUnit.SECONDS.toMillis(2));
794 
795         // Let the handler run.
796         latch.countDown();
797         mInjector.waitForHandler();
798 
799         List<BrightnessChangeEvent> events = mTracker.getEvents(0, true).getList();
800         mTracker.stop();
801 
802         // Check event was recorded with time it was sent rather than handler ran.
803         assertEquals(1, events.size());
804         BrightnessChangeEvent event = events.get(0);
805         assertEquals(eventTime, event.timeStamp);
806     }
807 
808     @Test
testDisplayIdChange()809     public void testDisplayIdChange() {
810         float firstBrightness = 0.5f;
811         float secondBrightness = 0.75f;
812         String firstDisplayId = "123";
813         String secondDisplayId = "456";
814 
815         startTracker(mTracker);
816         mInjector.mSensorListener.onSensorChanged(createSensorEvent(1000.0f));
817 
818         notifyBrightnessChanged(mTracker, firstBrightness, firstDisplayId);
819         mInjector.incrementTime(TimeUnit.SECONDS.toMillis(2));
820         List<BrightnessChangeEvent> events = mTracker.getEvents(0, true).getList();
821         assertEquals(1, events.size());
822         BrightnessChangeEvent firstEvent = events.get(0);
823         assertEquals(firstDisplayId, firstEvent.uniqueDisplayId);
824         assertEquals(firstBrightness, firstEvent.brightness, 0.001f);
825 
826         notifyBrightnessChanged(mTracker, secondBrightness, secondDisplayId);
827         mInjector.incrementTime(TimeUnit.SECONDS.toMillis(2));
828         events = mTracker.getEvents(0, true).getList();
829         assertEquals(2, events.size());
830         BrightnessChangeEvent secondEvent = events.get(1);
831         assertEquals(secondDisplayId, secondEvent.uniqueDisplayId);
832         assertEquals(secondBrightness, secondEvent.brightness, 0.001f);
833 
834         mTracker.stop();
835     }
836 
getInputStream(String data)837     private InputStream getInputStream(String data) {
838         return new ByteArrayInputStream(data.getBytes(StandardCharsets.UTF_8));
839     }
840 
batteryChangeEvent(int level, int scale)841     private Intent batteryChangeEvent(int level, int scale) {
842         Intent intent = new Intent();
843         intent.setAction(Intent.ACTION_BATTERY_CHANGED);
844         intent.putExtra(BatteryManager.EXTRA_LEVEL, level);
845         intent.putExtra(BatteryManager.EXTRA_SCALE, scale);
846         return intent;
847     }
848 
createSensorEvent(float lux)849     private SensorEvent createSensorEvent(float lux) {
850         SensorEvent event;
851         try {
852             Constructor<SensorEvent> constr =
853                     SensorEvent.class.getDeclaredConstructor(Integer.TYPE);
854             constr.setAccessible(true);
855             event = constr.newInstance(1);
856         } catch (Exception e) {
857             throw new RuntimeException(e);
858         }
859         event.values[0] = lux;
860         event.timestamp = mInjector.mElapsedRealtimeNanos;
861 
862         return event;
863     }
864 
startTracker(BrightnessTracker tracker)865     private void startTracker(BrightnessTracker tracker) {
866         startTracker(tracker, DEFAULT_INITIAL_BRIGHTNESS,  DEFAULT_COLOR_SAMPLING_ENABLED);
867     }
868 
startTracker(BrightnessTracker tracker, float initialBrightness, boolean collectColorSamples)869     private void startTracker(BrightnessTracker tracker, float initialBrightness,
870             boolean collectColorSamples) {
871         tracker.start(initialBrightness);
872         tracker.setBrightnessConfiguration(buildBrightnessConfiguration(collectColorSamples));
873         mInjector.waitForHandler();
874     }
875 
notifyBrightnessChanged(BrightnessTracker tracker, float brightness)876     private void notifyBrightnessChanged(BrightnessTracker tracker, float brightness) {
877         notifyBrightnessChanged(tracker, brightness, DEFAULT_DISPLAY_ID);
878     }
879 
notifyBrightnessChanged(BrightnessTracker tracker, float brightness, String displayId)880     private void notifyBrightnessChanged(BrightnessTracker tracker, float brightness,
881             String displayId) {
882         notifyBrightnessChanged(tracker, brightness, true /*userInitiated*/,
883                 1.0f /*powerBrightnessFactor*/, false /*isUserSetBrightness*/,
884                 false /*isDefaultBrightnessConfig*/, displayId);
885     }
886 
notifyBrightnessChanged(BrightnessTracker tracker, float brightness, boolean userInitiated, float powerBrightnessFactor, boolean isUserSetBrightness, boolean isDefaultBrightnessConfig, String displayId)887     private void notifyBrightnessChanged(BrightnessTracker tracker, float brightness,
888             boolean userInitiated, float powerBrightnessFactor, boolean isUserSetBrightness,
889             boolean isDefaultBrightnessConfig, String displayId) {
890         tracker.notifyBrightnessChanged(brightness, userInitiated, powerBrightnessFactor,
891                 isUserSetBrightness, isDefaultBrightnessConfig, displayId);
892         mInjector.waitForHandler();
893     }
894 
buildBrightnessConfiguration(boolean collectColorSamples)895     private BrightnessConfiguration buildBrightnessConfiguration(boolean collectColorSamples) {
896         BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder(
897                 /* lux = */ new float[] {0f, 10f, 100f},
898                 /* nits = */ new float[] {1f, 90f, 100f});
899         builder.setShouldCollectColorSamples(collectColorSamples);
900         return builder.build();
901     }
902 
903     private static final class Idle implements MessageQueue.IdleHandler {
904         private boolean mIdle;
905 
906         @Override
queueIdle()907         public boolean queueIdle() {
908             synchronized (this) {
909                 mIdle = true;
910                 notifyAll();
911             }
912             return false;
913         }
914 
waitForIdle()915         public synchronized void waitForIdle() {
916             while (!mIdle) {
917                 try {
918                     wait();
919                 } catch (InterruptedException e) {
920                 }
921             }
922         }
923     }
924 
925     private class TestInjector extends BrightnessTracker.Injector {
926         SensorEventListener mSensorListener;
927         BroadcastReceiver mBroadcastReceiver;
928         DisplayManager.DisplayListener mDisplayListener;
929         Map<String, Integer> mSecureIntSettings = new HashMap<>();
930         long mCurrentTimeMillis = System.currentTimeMillis();
931         long mElapsedRealtimeNanos = SystemClock.elapsedRealtimeNanos();
932         Handler mHandler;
933         boolean mIdleScheduled;
934         boolean mInteractive = true;
935         int[] mProfiles;
936         ContentObserver mContentObserver;
937         boolean mIsBrightnessModeAutomatic = true;
938         boolean mColorSamplingEnabled = false;
939         DisplayedContentSamplingAttributes mDefaultSamplingAttributes =
940                 new DisplayedContentSamplingAttributes(0x37, 0, 0x4);
941         float mFrameRate = 60.0f;
942         int mNoColorSamplingFrames;
943 
944 
TestInjector(Handler handler)945         public TestInjector(Handler handler) {
946             mHandler = handler;
947         }
948 
incrementTime(long timeMillis)949         void incrementTime(long timeMillis) {
950             mCurrentTimeMillis += timeMillis;
951             mElapsedRealtimeNanos += TimeUnit.MILLISECONDS.toNanos(timeMillis);
952         }
953 
setBrightnessMode(boolean isBrightnessModeAutomatic)954         void setBrightnessMode(boolean isBrightnessModeAutomatic) {
955           mIsBrightnessModeAutomatic = isBrightnessModeAutomatic;
956           mContentObserver.dispatchChange(false, null);
957           waitForHandler();
958         }
959 
sendScreenChange(boolean screenOn)960         void sendScreenChange(boolean screenOn) {
961             mInteractive = screenOn;
962             Intent intent = new Intent();
963             intent.setAction(screenOn ? Intent.ACTION_SCREEN_ON : Intent.ACTION_SCREEN_OFF);
964             mBroadcastReceiver.onReceive(InstrumentationRegistry.getContext(), intent);
965             waitForHandler();
966         }
967 
waitForHandler()968         void waitForHandler() {
969             Idle idle = new Idle();
970             mHandler.getLooper().getQueue().addIdleHandler(idle);
971             mHandler.post(() -> {});
972             idle.waitForIdle();
973         }
974 
975         @Override
registerSensorListener(Context context, SensorEventListener sensorListener, Handler handler)976         public void registerSensorListener(Context context,
977                 SensorEventListener sensorListener, Handler handler) {
978             mSensorListener = sensorListener;
979         }
980 
981         @Override
unregisterSensorListener(Context context, SensorEventListener sensorListener)982         public void unregisterSensorListener(Context context,
983                 SensorEventListener sensorListener) {
984             mSensorListener = null;
985         }
986 
987         @Override
registerBrightnessModeObserver(ContentResolver resolver, ContentObserver settingsObserver)988         public void registerBrightnessModeObserver(ContentResolver resolver,
989                 ContentObserver settingsObserver) {
990             mContentObserver = settingsObserver;
991         }
992 
993         @Override
unregisterBrightnessModeObserver(Context context, ContentObserver settingsObserver)994         public void unregisterBrightnessModeObserver(Context context,
995                 ContentObserver settingsObserver) {
996             mContentObserver = null;
997         }
998 
999         @Override
registerReceiver(Context context, BroadcastReceiver shutdownReceiver, IntentFilter shutdownFilter)1000         public void registerReceiver(Context context,
1001                 BroadcastReceiver shutdownReceiver, IntentFilter shutdownFilter) {
1002             mBroadcastReceiver = shutdownReceiver;
1003         }
1004 
1005         @Override
unregisterReceiver(Context context, BroadcastReceiver broadcastReceiver)1006         public void unregisterReceiver(Context context,
1007                 BroadcastReceiver broadcastReceiver) {
1008             assertEquals(mBroadcastReceiver, broadcastReceiver);
1009             mBroadcastReceiver = null;
1010         }
1011 
1012         @Override
getBackgroundHandler()1013         public Handler getBackgroundHandler() {
1014             return mHandler;
1015         }
1016 
1017         @Override
isBrightnessModeAutomatic(ContentResolver resolver)1018         public boolean isBrightnessModeAutomatic(ContentResolver resolver) {
1019             return mIsBrightnessModeAutomatic;
1020         }
1021 
1022         @Override
getSecureIntForUser(ContentResolver resolver, String setting, int defaultValue, int userId)1023         public int getSecureIntForUser(ContentResolver resolver, String setting, int defaultValue,
1024                 int userId) {
1025             Integer value = mSecureIntSettings.get(setting);
1026             if (value == null) {
1027                 return defaultValue;
1028             } else {
1029                 return value;
1030             }
1031         }
1032 
1033         @Override
getFile(String filename)1034         public AtomicFile getFile(String filename) {
1035             // Don't have the test write / read from anywhere.
1036             return null;
1037         }
1038 
1039         @Override
currentTimeMillis()1040         public long currentTimeMillis() {
1041             return mCurrentTimeMillis;
1042         }
1043 
1044         @Override
elapsedRealtimeNanos()1045         public long elapsedRealtimeNanos() {
1046             return mElapsedRealtimeNanos;
1047         }
1048 
1049         @Override
getUserSerialNumber(UserManager userManager, int userId)1050         public int getUserSerialNumber(UserManager userManager, int userId) {
1051             return userId + 10;
1052         }
1053 
1054         @Override
getUserId(UserManager userManager, int userSerialNumber)1055         public int getUserId(UserManager userManager, int userSerialNumber) {
1056             return userSerialNumber - 10;
1057         }
1058 
1059         @Override
getProfileIds(UserManager userManager, int userId)1060         public int[] getProfileIds(UserManager userManager, int userId) {
1061             if (mProfiles != null) {
1062                 return mProfiles;
1063             } else {
1064                 return new int[]{userId};
1065             }
1066         }
1067 
1068         @Override
getFocusedStack()1069         public RootTaskInfo getFocusedStack() throws RemoteException {
1070             RootTaskInfo focusedStack = new RootTaskInfo();
1071             focusedStack.userId = 0;
1072             focusedStack.topActivity = new ComponentName("a.package", "a.class");
1073             return focusedStack;
1074         }
1075 
1076         @Override
scheduleIdleJob(Context context)1077         public void scheduleIdleJob(Context context) {
1078             // Don't actually schedule jobs during unit tests.
1079             mIdleScheduled = true;
1080         }
1081 
1082         @Override
cancelIdleJob(Context context)1083         public void cancelIdleJob(Context context) {
1084             mIdleScheduled = false;
1085         }
1086 
1087         @Override
isInteractive(Context context)1088         public boolean isInteractive(Context context) {
1089             return mInteractive;
1090         }
1091 
1092         @Override
getNightDisplayColorTemperature(Context context)1093         public int getNightDisplayColorTemperature(Context context) {
1094           return mSecureIntSettings.getOrDefault(Settings.Secure.NIGHT_DISPLAY_COLOR_TEMPERATURE,
1095                   mDefaultNightModeColorTemperature);
1096         }
1097 
1098         @Override
isNightDisplayActivated(Context context)1099         public boolean isNightDisplayActivated(Context context) {
1100             return mSecureIntSettings.getOrDefault(Settings.Secure.NIGHT_DISPLAY_ACTIVATED,
1101                     0) == 1;
1102         }
1103 
1104         @Override
getReduceBrightColorsStrength(Context context)1105         public int getReduceBrightColorsStrength(Context context) {
1106             return mSecureIntSettings.getOrDefault(Settings.Secure.REDUCE_BRIGHT_COLORS_LEVEL,
1107                     0);
1108         }
1109 
1110         @Override
isReduceBrightColorsActivated(Context context)1111         public boolean isReduceBrightColorsActivated(Context context) {
1112             return mSecureIntSettings.getOrDefault(Settings.Secure.REDUCE_BRIGHT_COLORS_ACTIVATED,
1113                     0) == 1;
1114         }
1115 
1116         @Override
sampleColor(int noFramesToSample)1117         public DisplayedContentSample sampleColor(int noFramesToSample) {
1118             return new DisplayedContentSample(600L,
1119                     null,
1120                     null,
1121                      new long[] {1, 10, 100, 1000, 300, 30, 10, 1},
1122                     null);
1123         }
1124 
1125         @Override
getFrameRate(Context context)1126         public float getFrameRate(Context context) {
1127             return mFrameRate;
1128         }
1129 
1130         @Override
getSamplingAttributes()1131         public DisplayedContentSamplingAttributes getSamplingAttributes() {
1132             return mDefaultSamplingAttributes;
1133         }
1134 
1135         @Override
enableColorSampling(boolean enable, int noFrames)1136         public boolean enableColorSampling(boolean enable, int noFrames) {
1137             mColorSamplingEnabled = enable;
1138             mNoColorSamplingFrames = noFrames;
1139             return true;
1140         }
1141 
1142         @Override
registerDisplayListener(Context context, DisplayManager.DisplayListener listener, Handler handler)1143         public void registerDisplayListener(Context context,
1144                 DisplayManager.DisplayListener listener, Handler handler) {
1145             mDisplayListener = listener;
1146         }
1147 
1148         @Override
unRegisterDisplayListener(Context context, DisplayManager.DisplayListener listener)1149         public void unRegisterDisplayListener(Context context,
1150                 DisplayManager.DisplayListener listener) {
1151             mDisplayListener = null;
1152         }
1153     }
1154 }
1155