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