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