Refactor idle/low-light state management.
- remove custom idle timeout, now dreams are triggered by system inactivity - remove mDozeToDreamLock, which wakes up the device briefly from dozing, and puts it to dream. Sync with PowerManager on a better approach. Test: atest IdleHostViewControllerTest Bug: 195606657 Fix: 195606657 Change-Id: Ife31527affa3943d5bce4c5ffad35ec33a397528
This commit is contained in:
@@ -638,9 +638,6 @@
|
||||
screen on inactivity. -->
|
||||
<bool name="config_enableIdleMode">false</bool>
|
||||
|
||||
<!-- Timeout to idle mode duration in milliseconds. -->
|
||||
<integer name="config_idleModeTimeout">10000</integer>
|
||||
|
||||
<!-- This value is used when calculating whether the device is in ambient light mode. It is
|
||||
light mode when the light sensor sample value exceeds above this value. -->
|
||||
<integer name="config_ambientLightModeThreshold">5</integer>
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* 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.content.Context;
|
||||
import android.service.dreams.Sandman;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
/**
|
||||
* A helper class to the idle mode for requests related to the
|
||||
* {@link DreamService}.
|
||||
*/
|
||||
public class DreamHelper {
|
||||
@Inject
|
||||
protected DreamHelper() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests the system to start dreaming.
|
||||
*
|
||||
* @param context The context within which the dream request is sent.
|
||||
*/
|
||||
public void startDreaming(Context context) {
|
||||
Sandman.startDreamByUserRequest(context);
|
||||
}
|
||||
}
|
||||
@@ -24,22 +24,17 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Looper;
|
||||
import android.os.PowerManager;
|
||||
import android.os.SystemClock;
|
||||
import android.util.Log;
|
||||
import android.view.Choreographer;
|
||||
import android.view.View;
|
||||
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.broadcast.BroadcastDispatcher;
|
||||
import com.android.systemui.dagger.qualifiers.Main;
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||
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.ViewController;
|
||||
import com.android.systemui.util.concurrency.DelayableExecutor;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
@@ -52,13 +47,12 @@ import javax.inject.Provider;
|
||||
* {@link IdleHostViewController} processes signals to control the lifecycle of the idle screen.
|
||||
*/
|
||||
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);
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@IntDef({STATE_IDLE_MODE_ENABLED, STATE_KEYGUARD_SHOWING, STATE_DOZING, STATE_DREAMING,
|
||||
STATE_LOW_LIGHT, STATE_IDLING, STATE_SHOULD_START_IDLING})
|
||||
STATE_LOW_LIGHT})
|
||||
public @interface State {}
|
||||
|
||||
// Set at construction to indicate idle mode is available.
|
||||
@@ -76,76 +70,27 @@ public class IdleHostViewController extends ViewController<IdleHostView> {
|
||||
// Set when the device is in a low light environment.
|
||||
private static final int STATE_LOW_LIGHT = 1 << 4;
|
||||
|
||||
// Set when the device is idling, which is either dozing or dreaming.
|
||||
private static final int STATE_IDLING = 1 << 5;
|
||||
|
||||
// Set when the controller decides that the device should start idling (either dozing or
|
||||
// dreaming).
|
||||
private static final int STATE_SHOULD_START_IDLING = 1 << 6;
|
||||
|
||||
// The aggregate current state.
|
||||
private int mState;
|
||||
private boolean mIdleModeActive;
|
||||
private boolean mLowLightModeActive;
|
||||
private boolean mIsMonitoringLowLight;
|
||||
private boolean mIsMonitoringDream;
|
||||
|
||||
// Whether in a state waiting for dozing to complete before starting dreaming.
|
||||
private boolean mDozeToDreamLock = false;
|
||||
|
||||
private final Context mContext;
|
||||
|
||||
// Timeout to idle in milliseconds.
|
||||
private final int mIdleTimeout;
|
||||
|
||||
// Factory for generating input listeners.
|
||||
private final InputMonitorFactory mInputMonitorFactory;
|
||||
|
||||
// Delayable executor.
|
||||
private final DelayableExecutor mDelayableExecutor;
|
||||
|
||||
private final BroadcastDispatcher mBroadcastDispatcher;
|
||||
|
||||
private final PowerManager mPowerManager;
|
||||
|
||||
// Runnable for canceling enabling idle.
|
||||
private Runnable mCancelEnableIdling;
|
||||
|
||||
// Keyguard state controller for monitoring keyguard show state.
|
||||
private final KeyguardStateController mKeyguardStateController;
|
||||
|
||||
// Status bar state controller for monitoring when the device is dozing.
|
||||
private final StatusBarStateController mStatusBarStateController;
|
||||
|
||||
// Looper to use for monitoring input.
|
||||
private final Looper mLooper;
|
||||
|
||||
// Choreographer to use for monitoring input.
|
||||
private final Choreographer mChoreographer;
|
||||
|
||||
// Helper class for DreamService related requests.
|
||||
private final DreamHelper mDreamHelper;
|
||||
|
||||
// Monitor for tracking touches for activity.
|
||||
private InputMonitorCompat mInputMonitor;
|
||||
|
||||
// Input receiver of touch activities.
|
||||
private InputChannelCompat.InputEventReceiver mInputEventReceiver;
|
||||
|
||||
// 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) {
|
||||
Log.d(TAG, "time out, should start idling");
|
||||
}
|
||||
setState(STATE_SHOULD_START_IDLING, true);
|
||||
};
|
||||
|
||||
private final KeyguardStateController.Callback mKeyguardCallback =
|
||||
new KeyguardStateController.Callback() {
|
||||
@Override
|
||||
@@ -202,29 +147,20 @@ public class IdleHostViewController extends ViewController<IdleHostView> {
|
||||
|
||||
@Inject
|
||||
protected IdleHostViewController(
|
||||
Context context,
|
||||
BroadcastDispatcher broadcastDispatcher,
|
||||
PowerManager powerManager,
|
||||
IdleHostView view, InputMonitorFactory factory,
|
||||
@Main DelayableExecutor delayableExecutor,
|
||||
IdleHostView view,
|
||||
@Main Resources resources,
|
||||
@Main Looper looper,
|
||||
@Named(IDLE_VIEW) Provider<View> idleViewProvider,
|
||||
Choreographer choreographer,
|
||||
KeyguardStateController keyguardStateController,
|
||||
StatusBarStateController statusBarStateController,
|
||||
DreamHelper dreamHelper,
|
||||
AmbientLightModeMonitor ambientLightModeMonitor) {
|
||||
super(view);
|
||||
mContext = context;
|
||||
mBroadcastDispatcher = broadcastDispatcher;
|
||||
mPowerManager = powerManager;
|
||||
mIdleViewProvider = idleViewProvider;
|
||||
mKeyguardStateController = keyguardStateController;
|
||||
mStatusBarStateController = statusBarStateController;
|
||||
mLooper = looper;
|
||||
mChoreographer = choreographer;
|
||||
mDreamHelper = dreamHelper;
|
||||
mAmbientLightModeMonitor = ambientLightModeMonitor;
|
||||
|
||||
mState = STATE_KEYGUARD_SHOWING;
|
||||
@@ -236,13 +172,8 @@ public class IdleHostViewController extends ViewController<IdleHostView> {
|
||||
|
||||
setState(mState, true);
|
||||
|
||||
mIdleTimeout = resources.getInteger(R.integer.config_idleModeTimeout);
|
||||
mInputMonitorFactory = factory;
|
||||
mDelayableExecutor = delayableExecutor;
|
||||
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "initial state:" + mState + " enabled:" + enabled
|
||||
+ " timeout:" + mIdleTimeout);
|
||||
Log.d(TAG, "initial state:" + mState + " enabled:" + enabled);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -255,20 +186,6 @@ public class IdleHostViewController extends ViewController<IdleHostView> {
|
||||
}
|
||||
|
||||
private void setState(@State int state, boolean active) {
|
||||
// If waiting for dozing to stop, ignore any state update until dozing is stopped.
|
||||
if (mDozeToDreamLock) {
|
||||
if (state == STATE_DOZING && !active) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "dozing stopped, now start dreaming");
|
||||
}
|
||||
|
||||
mDozeToDreamLock = false;
|
||||
enableIdleMode(true);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
final int oldState = mState;
|
||||
|
||||
if (active) {
|
||||
@@ -281,53 +198,20 @@ public class IdleHostViewController extends ViewController<IdleHostView> {
|
||||
return;
|
||||
}
|
||||
|
||||
// Updates STATE_IDLING.
|
||||
final boolean isIdling = getState(STATE_DOZING) || getState(STATE_DREAMING);
|
||||
if (isIdling) {
|
||||
mState |= STATE_IDLING;
|
||||
} else {
|
||||
mState &= ~STATE_IDLING;
|
||||
}
|
||||
|
||||
// Updates STATE_SHOULD_START_IDLING.
|
||||
final boolean stoppedIdling = stoppedIdling(oldState);
|
||||
if (stoppedIdling) {
|
||||
mState &= ~STATE_SHOULD_START_IDLING;
|
||||
} else if (shouldStartIdling(oldState)) {
|
||||
mState |= STATE_SHOULD_START_IDLING;
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "set " + getStateName(state) + " to " + active);
|
||||
logCurrentState();
|
||||
}
|
||||
|
||||
final boolean wasLowLight = getState(STATE_LOW_LIGHT, oldState);
|
||||
final boolean isLowLight = getState(STATE_LOW_LIGHT);
|
||||
final boolean wasIdling = getState(STATE_IDLING, oldState);
|
||||
|
||||
// When the device is idling and no longer in low light, wake up from dozing, wait till
|
||||
// done, and start dreaming.
|
||||
if (wasLowLight && !isLowLight && wasIdling && isIdling) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "idling and no longer in low light, stop dozing");
|
||||
}
|
||||
|
||||
mDozeToDreamLock = true;
|
||||
|
||||
enableLowLightMode(false);
|
||||
return;
|
||||
}
|
||||
|
||||
final boolean inCommunalMode = getState(STATE_IDLE_MODE_ENABLED)
|
||||
&& getState(STATE_KEYGUARD_SHOWING);
|
||||
|
||||
enableDreamMonitoring(inCommunalMode);
|
||||
enableLowLightMonitoring(inCommunalMode);
|
||||
enableIdleMonitoring(inCommunalMode && !getState(STATE_IDLING));
|
||||
enableIdleMode(inCommunalMode && !getState(STATE_LOW_LIGHT)
|
||||
&& getState(STATE_SHOULD_START_IDLING));
|
||||
enableLowLightMode(inCommunalMode && !stoppedIdling && getState(STATE_LOW_LIGHT));
|
||||
|
||||
if (state == STATE_LOW_LIGHT) {
|
||||
enableLowLightMode(inCommunalMode && active);
|
||||
}
|
||||
}
|
||||
|
||||
private void enableDreamMonitoring(boolean enable) {
|
||||
@@ -354,64 +238,6 @@ public class IdleHostViewController extends ViewController<IdleHostView> {
|
||||
}
|
||||
}
|
||||
|
||||
private void enableIdleMonitoring(boolean enable) {
|
||||
if (enable && mInputMonitor == null && mInputEventReceiver == null) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "enable idle monitoring");
|
||||
}
|
||||
// Set initial timeout to idle.
|
||||
mCancelEnableIdling = mDelayableExecutor.executeDelayed(mEnableIdlingCallback,
|
||||
mIdleTimeout);
|
||||
|
||||
// Monitor - any input should reset timer
|
||||
mInputMonitor = mInputMonitorFactory.getInputMonitor(INPUT_MONITOR_IDENTIFIER);
|
||||
mInputEventReceiver = mInputMonitor.getInputReceiver(mLooper, mChoreographer,
|
||||
v -> {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "touch detected, resetting timeout");
|
||||
}
|
||||
// When input is received, reset timeout.
|
||||
if (mCancelEnableIdling != null) {
|
||||
mCancelEnableIdling.run();
|
||||
mCancelEnableIdling = null;
|
||||
}
|
||||
mCancelEnableIdling = mDelayableExecutor.executeDelayed(
|
||||
mEnableIdlingCallback, mIdleTimeout);
|
||||
});
|
||||
} else if (!enable && mInputMonitor != null && mInputEventReceiver != null) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "disable idle monitoring");
|
||||
}
|
||||
// Clean up idle callback and touch monitoring.
|
||||
if (mCancelEnableIdling != null) {
|
||||
mCancelEnableIdling.run();
|
||||
mCancelEnableIdling = null;
|
||||
}
|
||||
|
||||
mInputEventReceiver.dispose();
|
||||
mInputMonitor.dispose();
|
||||
mInputEventReceiver = null;
|
||||
mInputMonitor = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void enableIdleMode(boolean enable) {
|
||||
if (mIdleModeActive == enable) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, (enable ? "enable" : "disable") + " idle mode");
|
||||
}
|
||||
|
||||
mIdleModeActive = enable;
|
||||
|
||||
if (mIdleModeActive) {
|
||||
// Start dream.
|
||||
mDreamHelper.startDreaming(mContext);
|
||||
}
|
||||
}
|
||||
|
||||
private void enableLowLightMonitoring(boolean enable) {
|
||||
if (enable == mIsMonitoringLowLight) {
|
||||
return;
|
||||
@@ -429,13 +255,11 @@ public class IdleHostViewController extends ViewController<IdleHostView> {
|
||||
}
|
||||
|
||||
private void enableLowLightMode(boolean enable) {
|
||||
if (mLowLightModeActive == enable) {
|
||||
if (enable == getState(STATE_DOZING)) {
|
||||
return;
|
||||
}
|
||||
|
||||
mLowLightModeActive = enable;
|
||||
|
||||
if (mLowLightModeActive) {
|
||||
if (enable) {
|
||||
if (DEBUG) Log.d(TAG, "enter low light, start dozing");
|
||||
|
||||
mPowerManager.goToSleep(
|
||||
@@ -464,19 +288,6 @@ public class IdleHostViewController extends ViewController<IdleHostView> {
|
||||
mStatusBarStateController.removeCallback(mStatusBarCallback);
|
||||
}
|
||||
|
||||
// Returns whether the device just stopped idling by comparing the previous state with the
|
||||
// current one.
|
||||
private boolean stoppedIdling(int oldState) {
|
||||
// The device stopped idling if it's no longer dreaming or dozing.
|
||||
return !getState(STATE_DOZING) && !getState(STATE_DREAMING)
|
||||
&& (getState(STATE_DOZING, oldState) || getState(STATE_DREAMING, oldState));
|
||||
}
|
||||
|
||||
private boolean shouldStartIdling(int oldState) {
|
||||
// Should start idling immediately if the device went in low light environment.
|
||||
return !getState(STATE_LOW_LIGHT, oldState) && getState(STATE_LOW_LIGHT);
|
||||
}
|
||||
|
||||
private String getStateName(@State int state) {
|
||||
switch (state) {
|
||||
case STATE_IDLE_MODE_ENABLED:
|
||||
@@ -489,10 +300,6 @@ public class IdleHostViewController extends ViewController<IdleHostView> {
|
||||
return "STATE_DREAMING";
|
||||
case STATE_LOW_LIGHT:
|
||||
return "STATE_LOW_LIGHT";
|
||||
case STATE_IDLING:
|
||||
return "STATE_IDLING";
|
||||
case STATE_SHOULD_START_IDLING:
|
||||
return "STATE_SHOULD_START_IDLING";
|
||||
default:
|
||||
return "STATE_UNKNOWN";
|
||||
}
|
||||
@@ -517,8 +324,6 @@ public class IdleHostViewController extends ViewController<IdleHostView> {
|
||||
+ "\t" + getStateLog(STATE_DOZING) + "\n"
|
||||
+ "\t" + getStateLog(STATE_DREAMING) + "\n"
|
||||
+ "\t" + getStateLog(STATE_LOW_LIGHT) + "\n"
|
||||
+ "\t" + getStateLog(STATE_IDLING) + "\n"
|
||||
+ "\t" + getStateLog(STATE_SHOULD_START_IDLING) + "\n"
|
||||
+ "}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,22 +16,16 @@
|
||||
|
||||
package com.android.systemui.idle;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.Mockito.atLeastOnce;
|
||||
import static org.mockito.Mockito.clearInvocations;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Looper;
|
||||
import android.os.PowerManager;
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.view.Choreographer;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
@@ -40,10 +34,7 @@ import com.android.systemui.R;
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.broadcast.BroadcastDispatcher;
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||
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 org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -60,22 +51,14 @@ public class IdleHostViewControllerTest extends SysuiTestCase {
|
||||
@Mock private BroadcastDispatcher mBroadcastDispatcher;
|
||||
@Mock private PowerManager mPowerManager;
|
||||
@Mock private IdleHostView mIdleHostView;
|
||||
@Mock private InputMonitorFactory mInputMonitorFactory;
|
||||
@Mock private DelayableExecutor mDelayableExecutor;
|
||||
@Mock private Resources mResources;
|
||||
@Mock private Looper mLooper;
|
||||
@Mock private Provider<View> mViewProvider;
|
||||
@Mock private Choreographer mChoreographer;
|
||||
@Mock private KeyguardStateController mKeyguardStateController;
|
||||
@Mock private StatusBarStateController mStatusBarStateController;
|
||||
@Mock private DreamHelper mDreamHelper;
|
||||
@Mock private InputMonitorCompat mInputMonitor;
|
||||
@Mock private InputChannelCompat.InputEventReceiver mInputEventReceiver;
|
||||
@Mock private AmbientLightModeMonitor mAmbientLightModeMonitor;
|
||||
|
||||
private KeyguardStateController.Callback mKeyguardStateCallback;
|
||||
private StatusBarStateController.StateListener mStatusBarStateListener;
|
||||
private IdleHostViewController mController;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
@@ -83,17 +66,12 @@ public class IdleHostViewControllerTest extends SysuiTestCase {
|
||||
|
||||
when(mResources.getBoolean(R.bool.config_enableIdleMode)).thenReturn(true);
|
||||
when(mStatusBarStateController.isDozing()).thenReturn(false);
|
||||
when(mInputMonitorFactory.getInputMonitor("IdleHostViewController"))
|
||||
.thenReturn(mInputMonitor);
|
||||
when(mInputMonitor.getInputReceiver(any(), any(), any())).thenReturn(mInputEventReceiver);
|
||||
|
||||
mController = new IdleHostViewController(mContext,
|
||||
mBroadcastDispatcher, mPowerManager, mIdleHostView,
|
||||
mInputMonitorFactory, mDelayableExecutor, mResources, mLooper, mViewProvider,
|
||||
mChoreographer, mKeyguardStateController, mStatusBarStateController, mDreamHelper,
|
||||
mAmbientLightModeMonitor);
|
||||
mController.init();
|
||||
mController.onViewAttached();
|
||||
final IdleHostViewController controller = new IdleHostViewController(mBroadcastDispatcher,
|
||||
mPowerManager, mIdleHostView, mResources, mViewProvider, mKeyguardStateController,
|
||||
mStatusBarStateController, mAmbientLightModeMonitor);
|
||||
controller.init();
|
||||
controller.onViewAttached();
|
||||
|
||||
// Captures keyguard state controller callback.
|
||||
ArgumentCaptor<KeyguardStateController.Callback> keyguardStateCallbackCaptor =
|
||||
@@ -108,101 +86,6 @@ public class IdleHostViewControllerTest extends SysuiTestCase {
|
||||
mStatusBarStateListener = statusBarStateListenerCaptor.getValue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTimeoutToIdleMode() {
|
||||
// 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());
|
||||
callbackCapture.getValue().run();
|
||||
|
||||
// Verifies start dreaming (idle mode).
|
||||
verify(mDreamHelper).startDreaming(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTimeoutToLowLightMode() {
|
||||
// Keyguard showing.
|
||||
when(mKeyguardStateController.isShowing()).thenReturn(true);
|
||||
mKeyguardStateCallback.onKeyguardShowingChanged();
|
||||
|
||||
// Captures dream broadcast receiver;
|
||||
ArgumentCaptor<BroadcastReceiver> dreamBroadcastReceiverCaptor =
|
||||
ArgumentCaptor.forClass(BroadcastReceiver.class);
|
||||
verify(mBroadcastDispatcher)
|
||||
.registerReceiver(dreamBroadcastReceiverCaptor.capture(), any());
|
||||
final BroadcastReceiver dreamBroadcastReceiver = dreamBroadcastReceiverCaptor.getValue();
|
||||
|
||||
// Low ambient lighting.
|
||||
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());
|
||||
|
||||
mStatusBarStateListener.onDozingChanged(true /*isDozing*/);
|
||||
dreamBroadcastReceiver.onReceive(mContext, new Intent(Intent.ACTION_DREAMING_STARTED));
|
||||
|
||||
// User wakes up the device.
|
||||
mStatusBarStateListener.onDozingChanged(false /*isDozing*/);
|
||||
dreamBroadcastReceiver.onReceive(mContext, new Intent(Intent.ACTION_DREAMING_STOPPED));
|
||||
|
||||
// Clears power manager invocations to make sure the below dozing was triggered by the
|
||||
// timeout.
|
||||
clearInvocations(mPowerManager);
|
||||
|
||||
// Times out.
|
||||
ArgumentCaptor<Runnable> callbackCapture = ArgumentCaptor.forClass(Runnable.class);
|
||||
verify(mDelayableExecutor, atLeastOnce()).executeDelayed(callbackCapture.capture(),
|
||||
anyLong());
|
||||
callbackCapture.getValue().run();
|
||||
|
||||
// Verifies go to sleep (low light mode).
|
||||
verify(mPowerManager).goToSleep(anyLong(), anyInt(), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransitionBetweenIdleAndLowLightMode() {
|
||||
// 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());
|
||||
callbackCapture.getValue().run();
|
||||
|
||||
// Verifies in idle mode (dreaming).
|
||||
verify(mDreamHelper).startDreaming(any());
|
||||
clearInvocations(mDreamHelper);
|
||||
|
||||
// Ambient lighting becomes dim.
|
||||
lightMonitorCallback.onChange(AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_DARK);
|
||||
|
||||
// Verifies in low light mode (dozing).
|
||||
verify(mPowerManager).goToSleep(anyLong(), anyInt(), anyInt());
|
||||
|
||||
// Ambient lighting becomes bright again.
|
||||
lightMonitorCallback.onChange(AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_LIGHT);
|
||||
|
||||
// Verifies in idle mode (dreaming).
|
||||
verify(mDreamHelper).startDreaming(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStartDozingWhenLowLight() {
|
||||
// Keyguard showing.
|
||||
@@ -225,20 +108,22 @@ public class IdleHostViewControllerTest extends SysuiTestCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInputEventReceiverLifecycle() {
|
||||
public void testWakeUpWhenRegularLight() {
|
||||
// Keyguard showing.
|
||||
when(mKeyguardStateController.isShowing()).thenReturn(true);
|
||||
mKeyguardStateCallback.onKeyguardShowingChanged();
|
||||
|
||||
// Should register input event receiver.
|
||||
verify(mInputMonitor).getInputReceiver(any(), any(), any());
|
||||
// In low light / dozing.
|
||||
final AmbientLightModeMonitor.Callback lightMonitorCallback =
|
||||
captureAmbientLightModeMonitorCallback();
|
||||
lightMonitorCallback.onChange(AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_DARK);
|
||||
mStatusBarStateListener.onDozingChanged(true /*isDozing*/);
|
||||
|
||||
// Keyguard dismissed.
|
||||
when(mKeyguardStateController.isShowing()).thenReturn(false);
|
||||
mKeyguardStateCallback.onKeyguardShowingChanged();
|
||||
// Regular ambient lighting.
|
||||
lightMonitorCallback.onChange(AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_LIGHT);
|
||||
|
||||
// Should dispose input event receiver.
|
||||
verify(mInputEventReceiver).dispose();
|
||||
// Verifies it wakes up from sleep.
|
||||
verify(mPowerManager).wakeUp(anyLong(), anyInt(), anyString());
|
||||
}
|
||||
|
||||
// Captures [AmbientLightModeMonitor.Callback] assuming that the ambient light mode monitor
|
||||
|
||||
Reference in New Issue
Block a user