Merge "Introduce AmbientLightModeMonitor."

This commit is contained in:
TreeHugger Robot
2021-10-14 19:51:00 +00:00
committed by Android (Google) Code Review
4 changed files with 353 additions and 75 deletions

View File

@@ -0,0 +1,127 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.idle
import android.annotation.IntDef
import android.hardware.Sensor
import android.hardware.SensorEvent
import android.hardware.SensorEventListener
import android.hardware.SensorManager
import android.util.Log
import com.android.systemui.util.sensors.AsyncSensorManager
import javax.inject.Inject
import kotlin.properties.Delegates
/**
* Monitors ambient light signals, applies a debouncing algorithm, and produces the current
* [AmbientLightMode].
*
* For debouncer behavior, refer to go/titan-light-sensor-debouncer.
*
* @property sensorManager the sensor manager used to register sensor event updates.
*/
class AmbientLightModeMonitor @Inject constructor(
private val sensorManager: AsyncSensorManager
) {
companion object {
private const val TAG = "AmbientLightModeMonitor"
private val DEBUG = Log.isLoggable(TAG, Log.DEBUG)
const val AMBIENT_LIGHT_MODE_LIGHT = 0
const val AMBIENT_LIGHT_MODE_DARK = 1
const val AMBIENT_LIGHT_MODE_UNDECIDED = 2
}
// Light sensor used to detect ambient lighting conditions.
private val lightSensor: Sensor = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT)
// Registered callback, which gets triggered when the ambient light mode changes.
private var callback: Callback? = null
// Represents all ambient light modes.
@Retention(AnnotationRetention.SOURCE)
@IntDef(AMBIENT_LIGHT_MODE_LIGHT, AMBIENT_LIGHT_MODE_DARK, AMBIENT_LIGHT_MODE_UNDECIDED)
annotation class AmbientLightMode
// The current ambient light mode.
@AmbientLightMode private var mode: Int by Delegates.observable(AMBIENT_LIGHT_MODE_UNDECIDED
) { _, old, new ->
if (old != new) {
callback?.onChange(new)
}
}
/**
* Start monitoring the current ambient light mode.
*
* @param callback callback that gets triggered when the ambient light mode changes. It also
* gets triggered immediately to update the current value when this function is called.
*/
fun start(callback: Callback) {
if (DEBUG) Log.d(TAG, "start monitoring ambient light mode")
if (this.callback != null) {
if (DEBUG) Log.w(TAG, "already started")
return
}
this.callback = callback
callback.onChange(mode)
sensorManager.registerListener(mSensorEventListener, lightSensor,
SensorManager.SENSOR_DELAY_NORMAL)
}
/**
* Stop monitoring the current ambient light mode.
*/
fun stop() {
if (DEBUG) Log.d(TAG, "stop monitoring ambient light mode")
if (callback == null) {
if (DEBUG) Log.w(TAG, "haven't started")
return
}
callback = null
sensorManager.unregisterListener(mSensorEventListener)
}
private val mSensorEventListener: SensorEventListener = object : SensorEventListener {
override fun onSensorChanged(event: SensorEvent) {
if (event.values.isEmpty()) {
if (DEBUG) Log.w(TAG, "SensorEvent doesn't have any value")
return
}
// TODO(b/201657509): add debouncing logic.
val shouldBeLowLight = event.values[0] < 10
mode = if (shouldBeLowLight) AMBIENT_LIGHT_MODE_DARK else AMBIENT_LIGHT_MODE_LIGHT
}
override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {
// Do nothing.
}
}
/**
* Interface of the ambient light mode callback, which gets triggered when the mode changes.
*/
interface Callback {
fun onChange(@AmbientLightMode mode: Int)
}
}

View File

@@ -24,10 +24,6 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Looper;
import android.os.PowerManager;
import android.os.SystemClock;
@@ -44,7 +40,6 @@ import com.android.systemui.shared.system.InputMonitorCompat;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.ViewController;
import com.android.systemui.util.concurrency.DelayableExecutor;
import com.android.systemui.util.sensors.AsyncSensorManager;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -56,8 +51,7 @@ import javax.inject.Provider;
/**
* {@link IdleHostViewController} processes signals to control the lifecycle of the idle screen.
*/
public class IdleHostViewController extends ViewController<IdleHostView> implements
SensorEventListener {
public class IdleHostViewController extends ViewController<IdleHostView> {
private static final String INPUT_MONITOR_IDENTIFIER = "IdleHostViewController";
private static final String TAG = "IdleHostViewController";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -114,11 +108,6 @@ public class IdleHostViewController extends ViewController<IdleHostView> impleme
private final PowerManager mPowerManager;
private final AsyncSensorManager mSensorManager;
// Light sensor used to detect low light condition.
private final Sensor mSensor;
// Runnable for canceling enabling idle.
private Runnable mCancelEnableIdling;
@@ -146,6 +135,9 @@ public class IdleHostViewController extends ViewController<IdleHostView> impleme
// Intent filter for receiving dream broadcasts.
private IntentFilter mDreamIntentFilter;
// Monitor for the current ambient light mode. Used to trigger / exit low-light mode.
private final AmbientLightModeMonitor mAmbientLightModeMonitor;
// Delayed callback for starting idling.
private final Runnable mEnableIdlingCallback = () -> {
if (DEBUG) {
@@ -181,6 +173,31 @@ public class IdleHostViewController extends ViewController<IdleHostView> impleme
}
};
private final AmbientLightModeMonitor.Callback mAmbientLightModeCallback =
mode -> {
boolean shouldBeLowLight;
switch (mode) {
case AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_UNDECIDED:
return;
case AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_LIGHT:
shouldBeLowLight = false;
break;
case AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_DARK:
shouldBeLowLight = true;
break;
default:
Log.w(TAG, "invalid ambient light mode");
return;
}
if (DEBUG) Log.d(TAG, "ambient light mode changed to " + mode);
final boolean isLowLight = getState(STATE_LOW_LIGHT);
if (shouldBeLowLight != isLowLight) {
setState(STATE_LOW_LIGHT, shouldBeLowLight);
}
};
final Provider<View> mIdleViewProvider;
@Inject
@@ -188,7 +205,6 @@ public class IdleHostViewController extends ViewController<IdleHostView> impleme
Context context,
BroadcastDispatcher broadcastDispatcher,
PowerManager powerManager,
AsyncSensorManager sensorManager,
IdleHostView view, InputMonitorFactory factory,
@Main DelayableExecutor delayableExecutor,
@Main Resources resources,
@@ -197,18 +213,19 @@ public class IdleHostViewController extends ViewController<IdleHostView> impleme
Choreographer choreographer,
KeyguardStateController keyguardStateController,
StatusBarStateController statusBarStateController,
DreamHelper dreamHelper) {
DreamHelper dreamHelper,
AmbientLightModeMonitor ambientLightModeMonitor) {
super(view);
mContext = context;
mBroadcastDispatcher = broadcastDispatcher;
mPowerManager = powerManager;
mSensorManager = sensorManager;
mIdleViewProvider = idleViewProvider;
mKeyguardStateController = keyguardStateController;
mStatusBarStateController = statusBarStateController;
mLooper = looper;
mChoreographer = choreographer;
mDreamHelper = dreamHelper;
mAmbientLightModeMonitor = ambientLightModeMonitor;
mState = STATE_KEYGUARD_SHOWING;
@@ -222,7 +239,6 @@ public class IdleHostViewController extends ViewController<IdleHostView> impleme
mIdleTimeout = resources.getInteger(R.integer.config_idleModeTimeout);
mInputMonitorFactory = factory;
mDelayableExecutor = delayableExecutor;
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
if (DEBUG) {
Log.d(TAG, "initial state:" + mState + " enabled:" + enabled
@@ -405,11 +421,10 @@ public class IdleHostViewController extends ViewController<IdleHostView> impleme
if (mIsMonitoringLowLight) {
if (DEBUG) Log.d(TAG, "enable low light monitoring");
mSensorManager.registerListener(this /*listener*/, mSensor,
SensorManager.SENSOR_DELAY_NORMAL);
mAmbientLightModeMonitor.start(mAmbientLightModeCallback);
} else {
if (DEBUG) Log.d(TAG, "disable low light monitoring");
mSensorManager.unregisterListener(this);
mAmbientLightModeMonitor.stop();
}
}
@@ -449,28 +464,6 @@ public class IdleHostViewController extends ViewController<IdleHostView> impleme
mStatusBarStateController.removeCallback(mStatusBarCallback);
}
@Override
public void onSensorChanged(SensorEvent event) {
if (event.values.length == 0) {
if (DEBUG) Log.w(TAG, "SensorEvent doesn't have value");
return;
}
final boolean shouldBeLowLight = event.values[0] < 10;
final boolean isLowLight = getState(STATE_LOW_LIGHT);
if (shouldBeLowLight != isLowLight) {
setState(STATE_LOW_LIGHT, shouldBeLowLight);
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
if (DEBUG) {
Log.d(TAG, "onAccuracyChanged accuracy=" + accuracy);
}
}
// Returns whether the device just stopped idling by comparing the previous state with the
// current one.
private boolean stoppedIdling(int oldState) {

View File

@@ -0,0 +1,160 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.idle
import android.hardware.Sensor
import android.hardware.SensorEvent
import android.hardware.SensorEventListener
import android.testing.AndroidTestingRunner
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.util.sensors.AsyncSensorManager
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
import org.mockito.Mock
import org.mockito.Mockito.verify
import org.mockito.Mockito.reset
import org.mockito.Mockito.mock
import org.mockito.Mockito.never
import org.mockito.Mockito.anyInt
import org.mockito.Mockito.any
import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
@SmallTest
@RunWith(AndroidTestingRunner::class)
class AmbientLightModeMonitorTest : SysuiTestCase() {
@Mock private lateinit var sensorManager: AsyncSensorManager
@Mock private lateinit var sensor: Sensor
private lateinit var ambientLightModeMonitor: AmbientLightModeMonitor
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
`when`(sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT)).thenReturn(sensor)
ambientLightModeMonitor = AmbientLightModeMonitor(sensorManager)
}
@Test
fun shouldTriggerCallbackImmediatelyOnStart() {
val callback = mock(AmbientLightModeMonitor.Callback::class.java)
ambientLightModeMonitor.start(callback)
// Monitor just started, should receive UNDECIDED.
verify(callback).onChange(AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_UNDECIDED)
// Receives SensorEvent, and now mode is LIGHT.
val sensorEventListener = captureSensorEventListener()
sensorEventListener.onSensorChanged(sensorEventWithSingleValue(15f))
// Stop monitor.
ambientLightModeMonitor.stop()
// Restart monitor.
reset(callback)
ambientLightModeMonitor.start(callback)
// Verify receiving current mode (LIGHT) immediately.
verify(callback).onChange(AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_LIGHT)
}
@Test
fun shouldReportDarkModeWhenSensorValueIsLessThanTen() {
val callback = mock(AmbientLightModeMonitor.Callback::class.java)
ambientLightModeMonitor.start(callback)
val sensorEventListener = captureSensorEventListener()
reset(callback)
sensorEventListener.onSensorChanged(sensorEventWithSingleValue(0f))
verify(callback).onChange(AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_DARK)
sensorEventListener.onSensorChanged(sensorEventWithSingleValue(1f))
verify(callback).onChange(AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_DARK)
sensorEventListener.onSensorChanged(sensorEventWithSingleValue(5f))
verify(callback).onChange(AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_DARK)
sensorEventListener.onSensorChanged(sensorEventWithSingleValue(9.9f))
verify(callback).onChange(AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_DARK)
}
@Test
fun shouldReportLightModeWhenSensorValueIsGreaterThanOrEqualToTen() {
val callback = mock(AmbientLightModeMonitor.Callback::class.java)
ambientLightModeMonitor.start(callback)
val sensorEventListener = captureSensorEventListener()
reset(callback)
sensorEventListener.onSensorChanged(sensorEventWithSingleValue(10f))
verify(callback).onChange(AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_LIGHT)
sensorEventListener.onSensorChanged(sensorEventWithSingleValue(10.1f))
verify(callback).onChange(AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_LIGHT)
sensorEventListener.onSensorChanged(sensorEventWithSingleValue(15f))
verify(callback).onChange(AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_LIGHT)
sensorEventListener.onSensorChanged(sensorEventWithSingleValue(100f))
verify(callback).onChange(AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_LIGHT)
}
@Test
fun shouldOnlyTriggerCallbackWhenValueChanges() {
val callback = mock(AmbientLightModeMonitor.Callback::class.java)
ambientLightModeMonitor.start(callback)
val sensorEventListener = captureSensorEventListener()
// Light mode, should trigger callback.
reset(callback)
sensorEventListener.onSensorChanged(sensorEventWithSingleValue(20f))
verify(callback).onChange(AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_LIGHT)
// Light mode again, should NOT trigger callback.
reset(callback)
sensorEventListener.onSensorChanged(sensorEventWithSingleValue(25f))
verify(callback, never()).onChange(AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_LIGHT)
// Dark mode, should trigger callback.
reset(callback)
sensorEventListener.onSensorChanged(sensorEventWithSingleValue(2f))
verify(callback).onChange(AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_DARK)
// Dark mode again, should not trigger callback.
reset(callback)
sensorEventListener.onSensorChanged(sensorEventWithSingleValue(3f))
verify(callback, never()).onChange(AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_DARK)
}
// Captures [SensorEventListener], assuming it has been registered with [sensorManager].
private fun captureSensorEventListener(): SensorEventListener {
val captor = ArgumentCaptor.forClass(SensorEventListener::class.java)
verify(sensorManager).registerListener(captor.capture(), any(), anyInt())
return captor.value
}
// Returns a [SensorEvent] with a single [value].
private fun sensorEventWithSingleValue(value: Float): SensorEvent {
return SensorEvent(sensor, 1, 1, FloatArray(1) { value })
}
}

View File

@@ -28,8 +28,6 @@ import static org.mockito.Mockito.when;
import android.content.BroadcastReceiver;
import android.content.Intent;
import android.content.res.Resources;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.os.Looper;
import android.os.PowerManager;
import android.testing.AndroidTestingRunner;
@@ -46,7 +44,6 @@ import com.android.systemui.shared.system.InputChannelCompat;
import com.android.systemui.shared.system.InputMonitorCompat;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.concurrency.DelayableExecutor;
import com.android.systemui.util.sensors.AsyncSensorManager;
import org.junit.Before;
import org.junit.Test;
@@ -55,8 +52,6 @@ import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.time.Instant;
import javax.inject.Provider;
@SmallTest
@@ -64,7 +59,6 @@ import javax.inject.Provider;
public class IdleHostViewControllerTest extends SysuiTestCase {
@Mock private BroadcastDispatcher mBroadcastDispatcher;
@Mock private PowerManager mPowerManager;
@Mock private AsyncSensorManager mSensorManager;
@Mock private IdleHostView mIdleHostView;
@Mock private InputMonitorFactory mInputMonitorFactory;
@Mock private DelayableExecutor mDelayableExecutor;
@@ -74,12 +68,11 @@ public class IdleHostViewControllerTest extends SysuiTestCase {
@Mock private Choreographer mChoreographer;
@Mock private KeyguardStateController mKeyguardStateController;
@Mock private StatusBarStateController mStatusBarStateController;
@Mock private Sensor mSensor;
@Mock private DreamHelper mDreamHelper;
@Mock private InputMonitorCompat mInputMonitor;
@Mock private InputChannelCompat.InputEventReceiver mInputEventReceiver;
@Mock private AmbientLightModeMonitor mAmbientLightModeMonitor;
private final long mTimestamp = Instant.now().toEpochMilli();
private KeyguardStateController.Callback mKeyguardStateCallback;
private StatusBarStateController.StateListener mStatusBarStateListener;
private IdleHostViewController mController;
@@ -90,15 +83,15 @@ public class IdleHostViewControllerTest extends SysuiTestCase {
when(mResources.getBoolean(R.bool.config_enableIdleMode)).thenReturn(true);
when(mStatusBarStateController.isDozing()).thenReturn(false);
when(mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT)).thenReturn(mSensor);
when(mInputMonitorFactory.getInputMonitor("IdleHostViewController"))
.thenReturn(mInputMonitor);
when(mInputMonitor.getInputReceiver(any(), any(), any())).thenReturn(mInputEventReceiver);
mController = new IdleHostViewController(mContext,
mBroadcastDispatcher, mPowerManager, mSensorManager, mIdleHostView,
mBroadcastDispatcher, mPowerManager, mIdleHostView,
mInputMonitorFactory, mDelayableExecutor, mResources, mLooper, mViewProvider,
mChoreographer, mKeyguardStateController, mStatusBarStateController, mDreamHelper);
mChoreographer, mKeyguardStateController, mStatusBarStateController, mDreamHelper,
mAmbientLightModeMonitor);
mController.init();
mController.onViewAttached();
@@ -122,9 +115,9 @@ public class IdleHostViewControllerTest extends SysuiTestCase {
mKeyguardStateCallback.onKeyguardShowingChanged();
// Regular ambient lighting.
final SensorEvent sensorEvent = new SensorEvent(mSensor, 3, mTimestamp,
new float[]{90});
mController.onSensorChanged(sensorEvent);
final AmbientLightModeMonitor.Callback lightMonitorCallback =
captureAmbientLightModeMonitorCallback();
lightMonitorCallback.onChange(AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_LIGHT);
// Times out.
ArgumentCaptor<Runnable> callbackCapture = ArgumentCaptor.forClass(Runnable.class);
@@ -149,9 +142,9 @@ public class IdleHostViewControllerTest extends SysuiTestCase {
final BroadcastReceiver dreamBroadcastReceiver = dreamBroadcastReceiverCaptor.getValue();
// Low ambient lighting.
final SensorEvent sensorEvent = new SensorEvent(mSensor, 3, mTimestamp,
new float[]{5});
mController.onSensorChanged(sensorEvent);
final AmbientLightModeMonitor.Callback lightMonitorCallback =
captureAmbientLightModeMonitorCallback();
lightMonitorCallback.onChange(AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_DARK);
// Verifies it goes to sleep because of low light.
verify(mPowerManager).goToSleep(anyLong(), anyInt(), anyInt());
@@ -179,15 +172,15 @@ public class IdleHostViewControllerTest extends SysuiTestCase {
@Test
public void testTransitionBetweenIdleAndLowLightMode() {
// Regular ambient lighting.
final SensorEvent sensorEventRegularLight = new SensorEvent(mSensor, 3, mTimestamp,
new float[]{90});
mController.onSensorChanged(sensorEventRegularLight);
// Keyguard showing.
when(mKeyguardStateController.isShowing()).thenReturn(true);
mKeyguardStateCallback.onKeyguardShowingChanged();
// Regular ambient lighting.
final AmbientLightModeMonitor.Callback lightMonitorCallback =
captureAmbientLightModeMonitorCallback();
lightMonitorCallback.onChange(AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_LIGHT);
// Times out.
ArgumentCaptor<Runnable> callbackCapture = ArgumentCaptor.forClass(Runnable.class);
verify(mDelayableExecutor).executeDelayed(callbackCapture.capture(), anyLong());
@@ -198,15 +191,13 @@ public class IdleHostViewControllerTest extends SysuiTestCase {
clearInvocations(mDreamHelper);
// Ambient lighting becomes dim.
final SensorEvent sensorEventLowLight = new SensorEvent(mSensor, 3, mTimestamp,
new float[]{5});
mController.onSensorChanged(sensorEventLowLight);
lightMonitorCallback.onChange(AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_DARK);
// Verifies in low light mode (dozing).
verify(mPowerManager).goToSleep(anyLong(), anyInt(), anyInt());
// Ambient lighting becomes bright again.
mController.onSensorChanged(sensorEventRegularLight);
lightMonitorCallback.onChange(AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_LIGHT);
// Verifies in idle mode (dreaming).
verify(mDreamHelper).startDreaming(any());
@@ -214,22 +205,20 @@ public class IdleHostViewControllerTest extends SysuiTestCase {
@Test
public void testStartDozingWhenLowLight() {
// Regular ambient lighting.
final SensorEvent sensorEventRegularLight = new SensorEvent(mSensor, 3, mTimestamp,
new float[]{90});
mController.onSensorChanged(sensorEventRegularLight);
// Keyguard showing.
when(mKeyguardStateController.isShowing()).thenReturn(true);
mKeyguardStateCallback.onKeyguardShowingChanged();
// Regular ambient lighting.
final AmbientLightModeMonitor.Callback lightMonitorCallback =
captureAmbientLightModeMonitorCallback();
lightMonitorCallback.onChange(AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_LIGHT);
// Verifies it doesn't go to sleep yet.
verify(mPowerManager, never()).goToSleep(anyLong(), anyInt(), anyInt());
// Ambient lighting becomes dim.
final SensorEvent sensorEventLowLight = new SensorEvent(mSensor, 3, mTimestamp,
new float[]{5});
mController.onSensorChanged(sensorEventLowLight);
lightMonitorCallback.onChange(AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_DARK);
// Verifies it goes to sleep.
verify(mPowerManager).goToSleep(anyLong(), anyInt(), anyInt());
@@ -251,4 +240,13 @@ public class IdleHostViewControllerTest extends SysuiTestCase {
// Should dispose input event receiver.
verify(mInputEventReceiver).dispose();
}
// Captures [AmbientLightModeMonitor.Callback] assuming that the ambient light mode monitor
// has been started.
private AmbientLightModeMonitor.Callback captureAmbientLightModeMonitorCallback() {
ArgumentCaptor<AmbientLightModeMonitor.Callback> captor =
ArgumentCaptor.forClass(AmbientLightModeMonitor.Callback.class);
verify(mAmbientLightModeMonitor).start(captor.capture());
return captor.getValue();
}
}