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