Merge "Remove idle directory in SystemUI."
This commit is contained in:
@@ -1,23 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ 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.
|
||||
-->
|
||||
|
||||
|
||||
<com.android.systemui.idle.IdleHostView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/idle_host_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
@@ -89,11 +89,6 @@
|
||||
layout="@layout/keyguard_status_view"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<include layout="@layout/idle_host_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<include layout="@layout/dock_info_overlay"/>
|
||||
|
||||
<FrameLayout
|
||||
|
||||
@@ -20,8 +20,6 @@ import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
@@ -30,9 +28,6 @@ import com.android.systemui.communal.CommunalSource;
|
||||
import com.android.systemui.communal.PackageObserver;
|
||||
import com.android.systemui.communal.conditions.CommunalSettingCondition;
|
||||
import com.android.systemui.dagger.qualifiers.Main;
|
||||
import com.android.systemui.idle.AmbientLightModeMonitor;
|
||||
import com.android.systemui.idle.LightSensorEventsDebounceAlgorithm;
|
||||
import com.android.systemui.idle.dagger.IdleViewComponent;
|
||||
import com.android.systemui.util.condition.Condition;
|
||||
import com.android.systemui.util.condition.Monitor;
|
||||
import com.android.systemui.util.condition.dagger.MonitorComponent;
|
||||
@@ -46,7 +41,6 @@ import java.util.Set;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Provider;
|
||||
|
||||
import dagger.Binds;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import dagger.multibindings.ElementsIntoSet;
|
||||
@@ -58,20 +52,10 @@ import dagger.multibindings.StringKey;
|
||||
*/
|
||||
@Module(subcomponents = {
|
||||
CommunalViewComponent.class,
|
||||
IdleViewComponent.class,
|
||||
})
|
||||
public interface CommunalModule {
|
||||
String IDLE_VIEW = "idle_view";
|
||||
String COMMUNAL_CONDITIONS = "communal_conditions";
|
||||
|
||||
/** */
|
||||
@Provides
|
||||
@Named(IDLE_VIEW)
|
||||
static View provideIdleView(Context context) {
|
||||
FrameLayout view = new FrameLayout(context);
|
||||
return view;
|
||||
}
|
||||
|
||||
/** */
|
||||
@Provides
|
||||
static Optional<CommunalSource.Observer> provideCommunalSourcePackageObserver(
|
||||
@@ -86,15 +70,6 @@ public interface CommunalModule {
|
||||
ComponentName.unflattenFromString(componentName).getPackageName()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides LightSensorEventsDebounceAlgorithm as an instance to DebounceAlgorithm interface.
|
||||
* @param algorithm the instance of algorithm that is bound to the interface.
|
||||
* @return the interface that is bound to.
|
||||
*/
|
||||
@Binds
|
||||
AmbientLightModeMonitor.DebounceAlgorithm ambientLightDebounceAlgorithm(
|
||||
LightSensorEventsDebounceAlgorithm algorithm);
|
||||
|
||||
/**
|
||||
* Provides a set of conditions that need to be fulfilled in order for Communal Mode to display.
|
||||
*/
|
||||
|
||||
@@ -1,116 +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.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
|
||||
|
||||
/**
|
||||
* Monitors ambient light signals, applies a debouncing algorithm, and produces the current
|
||||
* ambient light mode.
|
||||
*
|
||||
* @property algorithm the debounce algorithm which transforms light sensor events into an
|
||||
* ambient light mode.
|
||||
* @property sensorManager the sensor manager used to register sensor event updates.
|
||||
*/
|
||||
class AmbientLightModeMonitor @Inject constructor(
|
||||
private val algorithm: DebounceAlgorithm,
|
||||
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)
|
||||
|
||||
// Represents all ambient light modes.
|
||||
@Retention(AnnotationRetention.SOURCE)
|
||||
@IntDef(AMBIENT_LIGHT_MODE_LIGHT, AMBIENT_LIGHT_MODE_DARK, AMBIENT_LIGHT_MODE_UNDECIDED)
|
||||
annotation class AmbientLightMode
|
||||
|
||||
/**
|
||||
* Start monitoring the current ambient light mode.
|
||||
*
|
||||
* @param callback callback that gets triggered when the ambient light mode changes.
|
||||
*/
|
||||
fun start(callback: Callback) {
|
||||
if (DEBUG) Log.d(TAG, "start monitoring ambient light mode")
|
||||
|
||||
if (lightSensor == null) {
|
||||
if (DEBUG) Log.w(TAG, "light sensor not available")
|
||||
return
|
||||
}
|
||||
|
||||
algorithm.start(callback)
|
||||
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")
|
||||
|
||||
algorithm.stop()
|
||||
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
|
||||
}
|
||||
|
||||
algorithm.onUpdateLightSensorEvent(event.values[0])
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface of the algorithm that transforms light sensor events to an ambient light mode.
|
||||
*/
|
||||
interface DebounceAlgorithm {
|
||||
// Setting Callback to nullable so mockito can verify without throwing NullPointerException.
|
||||
fun start(callback: Callback?)
|
||||
fun stop()
|
||||
fun onUpdateLightSensorEvent(value: Float)
|
||||
}
|
||||
}
|
||||
@@ -1,42 +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.util.AttributeSet;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* {@link IdleHostView} houses a surface to be displayed when the device idle.
|
||||
*/
|
||||
public class IdleHostView extends FrameLayout {
|
||||
public IdleHostView(@NonNull Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public IdleHostView(@NonNull Context context,
|
||||
@Nullable AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public IdleHostView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
}
|
||||
@@ -1,329 +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 static com.android.systemui.communal.dagger.CommunalModule.IDLE_VIEW;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.res.Resources;
|
||||
import android.os.PowerManager;
|
||||
import android.os.SystemClock;
|
||||
import android.util.Log;
|
||||
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.statusbar.policy.KeyguardStateController;
|
||||
import com.android.systemui.util.ViewController;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
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 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})
|
||||
public @interface State {}
|
||||
|
||||
// Set at construction to indicate idle mode is available.
|
||||
private static final int STATE_IDLE_MODE_ENABLED = 1 << 0;
|
||||
|
||||
// Set when keyguard is present, even below a dream or AOD. AKA the device is locked.
|
||||
private static final int STATE_KEYGUARD_SHOWING = 1 << 1;
|
||||
|
||||
// Set when the device has entered a dozing / low power state.
|
||||
private static final int STATE_DOZING = 1 << 2;
|
||||
|
||||
// Set when the device has entered a dreaming state, which includes dozing.
|
||||
private static final int STATE_DREAMING = 1 << 3;
|
||||
|
||||
// Set when the device is in a low light environment.
|
||||
private static final int STATE_LOW_LIGHT = 1 << 4;
|
||||
|
||||
// The aggregate current state.
|
||||
private int mState;
|
||||
private boolean mIsMonitoringLowLight;
|
||||
private boolean mIsMonitoringDream;
|
||||
|
||||
private final BroadcastDispatcher mBroadcastDispatcher;
|
||||
|
||||
private final PowerManager mPowerManager;
|
||||
|
||||
// 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;
|
||||
|
||||
// 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;
|
||||
|
||||
private final KeyguardStateController.Callback mKeyguardCallback =
|
||||
new KeyguardStateController.Callback() {
|
||||
@Override
|
||||
public void onKeyguardShowingChanged() {
|
||||
setState(STATE_KEYGUARD_SHOWING, mKeyguardStateController.isShowing());
|
||||
}
|
||||
};
|
||||
|
||||
private final StatusBarStateController.StateListener mStatusBarCallback =
|
||||
new StatusBarStateController.StateListener() {
|
||||
@Override
|
||||
public void onDozingChanged(boolean isDozing) {
|
||||
setState(STATE_DOZING, isDozing);
|
||||
}
|
||||
};
|
||||
|
||||
private final BroadcastReceiver mDreamStateReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (Intent.ACTION_DREAMING_STARTED.equals(intent.getAction())) {
|
||||
setState(STATE_DREAMING, true);
|
||||
} else if (Intent.ACTION_DREAMING_STOPPED.equals(intent.getAction())) {
|
||||
setState(STATE_DREAMING, false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
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
|
||||
protected IdleHostViewController(
|
||||
BroadcastDispatcher broadcastDispatcher,
|
||||
PowerManager powerManager,
|
||||
IdleHostView view,
|
||||
@Main Resources resources,
|
||||
@Named(IDLE_VIEW) Provider<View> idleViewProvider,
|
||||
KeyguardStateController keyguardStateController,
|
||||
StatusBarStateController statusBarStateController,
|
||||
AmbientLightModeMonitor ambientLightModeMonitor) {
|
||||
super(view);
|
||||
mBroadcastDispatcher = broadcastDispatcher;
|
||||
mPowerManager = powerManager;
|
||||
mIdleViewProvider = idleViewProvider;
|
||||
mKeyguardStateController = keyguardStateController;
|
||||
mStatusBarStateController = statusBarStateController;
|
||||
mAmbientLightModeMonitor = ambientLightModeMonitor;
|
||||
|
||||
mState = STATE_KEYGUARD_SHOWING;
|
||||
|
||||
final boolean enabled = resources.getBoolean(R.bool.config_enableIdleMode);
|
||||
if (enabled) {
|
||||
mState |= STATE_IDLE_MODE_ENABLED;
|
||||
}
|
||||
|
||||
setState(mState, true);
|
||||
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "initial state:" + mState + " enabled:" + enabled);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
super.init();
|
||||
|
||||
setState(STATE_KEYGUARD_SHOWING, mKeyguardStateController.isShowing());
|
||||
setState(STATE_DOZING, mStatusBarStateController.isDozing());
|
||||
}
|
||||
|
||||
private void setState(@State int state, boolean active) {
|
||||
final int oldState = mState;
|
||||
|
||||
if (active) {
|
||||
mState |= state;
|
||||
} else {
|
||||
mState &= ~state;
|
||||
}
|
||||
|
||||
if (oldState == mState) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "set " + getStateName(state) + " to " + active);
|
||||
logCurrentState();
|
||||
}
|
||||
|
||||
final boolean inCommunalMode = getState(STATE_IDLE_MODE_ENABLED)
|
||||
&& getState(STATE_KEYGUARD_SHOWING);
|
||||
|
||||
enableDreamMonitoring(inCommunalMode);
|
||||
enableLowLightMonitoring(inCommunalMode);
|
||||
|
||||
if (state == STATE_LOW_LIGHT) {
|
||||
enableLowLightMode(inCommunalMode && active);
|
||||
}
|
||||
}
|
||||
|
||||
private void enableDreamMonitoring(boolean enable) {
|
||||
if (mIsMonitoringDream == enable) {
|
||||
return;
|
||||
}
|
||||
|
||||
mIsMonitoringDream = enable;
|
||||
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, (enable ? "enable" : "disable") + " dream monitoring");
|
||||
}
|
||||
|
||||
if (mDreamIntentFilter == null) {
|
||||
mDreamIntentFilter = new IntentFilter();
|
||||
mDreamIntentFilter.addAction(Intent.ACTION_DREAMING_STARTED);
|
||||
mDreamIntentFilter.addAction(Intent.ACTION_DREAMING_STOPPED);
|
||||
}
|
||||
|
||||
if (enable) {
|
||||
mBroadcastDispatcher.registerReceiver(mDreamStateReceiver, mDreamIntentFilter);
|
||||
} else {
|
||||
mBroadcastDispatcher.unregisterReceiver(mDreamStateReceiver);
|
||||
}
|
||||
}
|
||||
|
||||
private void enableLowLightMonitoring(boolean enable) {
|
||||
if (enable == mIsMonitoringLowLight) {
|
||||
return;
|
||||
}
|
||||
|
||||
mIsMonitoringLowLight = enable;
|
||||
|
||||
if (mIsMonitoringLowLight) {
|
||||
if (DEBUG) Log.d(TAG, "enable low light monitoring");
|
||||
mAmbientLightModeMonitor.start(mAmbientLightModeCallback);
|
||||
} else {
|
||||
if (DEBUG) Log.d(TAG, "disable low light monitoring");
|
||||
mAmbientLightModeMonitor.stop();
|
||||
}
|
||||
}
|
||||
|
||||
private void enableLowLightMode(boolean enable) {
|
||||
if (enable == getState(STATE_DOZING)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (enable) {
|
||||
if (DEBUG) Log.d(TAG, "enter low light, start dozing");
|
||||
|
||||
mPowerManager.goToSleep(
|
||||
SystemClock.uptimeMillis(),
|
||||
PowerManager.GO_TO_SLEEP_REASON_APPLICATION, 0);
|
||||
} else {
|
||||
if (DEBUG) Log.d(TAG, "exit low light, stop dozing");
|
||||
mPowerManager.wakeUp(SystemClock.uptimeMillis(),
|
||||
PowerManager.WAKE_REASON_APPLICATION, "Exit low light condition");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onViewAttached() {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "onViewAttached");
|
||||
}
|
||||
|
||||
mKeyguardStateController.addCallback(mKeyguardCallback);
|
||||
mStatusBarStateController.addCallback(mStatusBarCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onViewDetached() {
|
||||
mKeyguardStateController.removeCallback(mKeyguardCallback);
|
||||
mStatusBarStateController.removeCallback(mStatusBarCallback);
|
||||
}
|
||||
|
||||
private String getStateName(@State int state) {
|
||||
switch (state) {
|
||||
case STATE_IDLE_MODE_ENABLED:
|
||||
return "STATE_IDLE_MODE_ENABLED";
|
||||
case STATE_KEYGUARD_SHOWING:
|
||||
return "STATE_KEYGUARD_SHOWING";
|
||||
case STATE_DOZING:
|
||||
return "STATE_DOZING";
|
||||
case STATE_DREAMING:
|
||||
return "STATE_DREAMING";
|
||||
case STATE_LOW_LIGHT:
|
||||
return "STATE_LOW_LIGHT";
|
||||
default:
|
||||
return "STATE_UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
private boolean getState(@State int state) {
|
||||
return getState(state, mState);
|
||||
}
|
||||
|
||||
private boolean getState(@State int state, int oldState) {
|
||||
return (oldState & state) == state;
|
||||
}
|
||||
|
||||
private String getStateLog(@State int state) {
|
||||
return getStateName(state) + " = " + getState(state);
|
||||
}
|
||||
|
||||
private void logCurrentState() {
|
||||
Log.d(TAG, "current state: {\n"
|
||||
+ "\t" + getStateLog(STATE_IDLE_MODE_ENABLED) + "\n"
|
||||
+ "\t" + getStateLog(STATE_KEYGUARD_SHOWING) + "\n"
|
||||
+ "\t" + getStateLog(STATE_DOZING) + "\n"
|
||||
+ "\t" + getStateLog(STATE_DREAMING) + "\n"
|
||||
+ "\t" + getStateLog(STATE_LOW_LIGHT) + "\n"
|
||||
+ "}");
|
||||
}
|
||||
}
|
||||
@@ -1,44 +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 com.android.systemui.dagger.qualifiers.DisplayId;
|
||||
import com.android.systemui.shared.system.InputMonitorCompat;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
/**
|
||||
* {@link InputMonitorFactory} generates instances of {@link InputMonitorCompat}.
|
||||
*/
|
||||
public class InputMonitorFactory {
|
||||
private final int mDisplayId;
|
||||
|
||||
@Inject
|
||||
public InputMonitorFactory(@DisplayId int displayId) {
|
||||
mDisplayId = displayId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a new {@link InputMonitorCompat}.
|
||||
*
|
||||
* @param identifier Identifier to generate monitor with.
|
||||
* @return A {@link InputMonitorCompat} instance.
|
||||
*/
|
||||
public InputMonitorCompat getInputMonitor(String identifier) {
|
||||
return new InputMonitorCompat(identifier, mDisplayId);
|
||||
}
|
||||
}
|
||||
@@ -1,284 +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.res.Resources
|
||||
import android.util.Log
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.dagger.qualifiers.Main
|
||||
import com.android.systemui.util.concurrency.DelayableExecutor
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* An algorithm that receives light sensor events, debounces the signals, and transforms into an
|
||||
* ambient light mode: light, dark, or undecided.
|
||||
*
|
||||
* More about the algorithm at go/titan-light-sensor-debouncer.
|
||||
*/
|
||||
class LightSensorEventsDebounceAlgorithm @Inject constructor(
|
||||
@Main private val executor: DelayableExecutor,
|
||||
@Main resources: Resources
|
||||
) : AmbientLightModeMonitor.DebounceAlgorithm {
|
||||
companion object {
|
||||
private const val TAG = "LightDebounceAlgorithm"
|
||||
private val DEBUG = Log.isLoggable(TAG, Log.DEBUG)
|
||||
}
|
||||
|
||||
// The ambient mode is considered light mode when the light sensor value increases exceeding
|
||||
// this value.
|
||||
private val lightModeThreshold =
|
||||
resources.getInteger(R.integer.config_ambientLightModeThreshold)
|
||||
|
||||
// The ambient mode is considered dark mode when the light sensor value drops below this
|
||||
// value.
|
||||
private val darkModeThreshold = resources.getInteger(R.integer.config_ambientDarkModeThreshold)
|
||||
|
||||
// Each sample for calculating light mode contains light sensor events collected for this
|
||||
// duration of time in milliseconds.
|
||||
private val lightSamplingSpanMillis =
|
||||
resources.getInteger(R.integer.config_ambientLightModeSamplingSpanMillis)
|
||||
|
||||
// Each sample for calculating dark mode contains light sensor events collected for this
|
||||
// duration of time in milliseconds.
|
||||
private val darkSamplingSpanMillis =
|
||||
resources.getInteger(R.integer.config_ambientDarkModeSamplingSpanMillis)
|
||||
|
||||
// The calculations for light mode is performed at this frequency in milliseconds.
|
||||
private val lightSamplingFrequencyMillis =
|
||||
resources.getInteger(R.integer.config_ambientLightModeSamplingFrequencyMillis)
|
||||
|
||||
// The calculations for dark mode is performed at this frequency in milliseconds.
|
||||
private val darkSamplingFrequencyMillis =
|
||||
resources.getInteger(R.integer.config_ambientDarkModeSamplingFrequencyMillis)
|
||||
|
||||
// Registered callback, which gets triggered when the ambient light mode changes.
|
||||
private var callback: AmbientLightModeMonitor.Callback? = null
|
||||
|
||||
// Queue of bundles used for calculating [isLightMode], ordered from oldest to latest.
|
||||
val bundlesQueueLightMode = ArrayList<ArrayList<Float>>()
|
||||
|
||||
// Queue of bundles used for calculating [isDarkMode], ordered from oldest to latest
|
||||
val bundlesQueueDarkMode = ArrayList<ArrayList<Float>>()
|
||||
|
||||
// The current ambient light mode.
|
||||
@AmbientLightModeMonitor.AmbientLightMode
|
||||
var mode = AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_UNDECIDED
|
||||
set(value) {
|
||||
if (field == value) return
|
||||
field = value
|
||||
|
||||
if (DEBUG) Log.d(TAG, "ambient light mode changed to $value")
|
||||
|
||||
callback?.onChange(value)
|
||||
}
|
||||
|
||||
// The latest claim of whether it should be light mode.
|
||||
var isLightMode = false
|
||||
set(value) {
|
||||
if (field == value) return
|
||||
field = value
|
||||
|
||||
if (DEBUG) Log.d(TAG, "isLightMode: $value")
|
||||
|
||||
mode = when {
|
||||
isDarkMode -> AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_DARK
|
||||
value -> AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_LIGHT
|
||||
else -> AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_UNDECIDED
|
||||
}
|
||||
}
|
||||
|
||||
// The latest claim of whether it should be dark mode.
|
||||
var isDarkMode = false
|
||||
set(value) {
|
||||
if (field == value) return
|
||||
field = value
|
||||
|
||||
if (DEBUG) Log.d(TAG, "isDarkMode: $value")
|
||||
|
||||
mode = when {
|
||||
value -> AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_DARK
|
||||
isLightMode -> AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_LIGHT
|
||||
else -> AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_UNDECIDED
|
||||
}
|
||||
}
|
||||
|
||||
// The latest average of the light mode bundle.
|
||||
var bundleAverageLightMode = 0.0
|
||||
set(value) {
|
||||
field = value
|
||||
|
||||
if (DEBUG) Log.d(TAG, "light mode average: $value")
|
||||
|
||||
isLightMode = value > lightModeThreshold
|
||||
}
|
||||
|
||||
// The latest average of the dark mode bundle.
|
||||
var bundleAverageDarkMode = 0.0
|
||||
set(value) {
|
||||
field = value
|
||||
|
||||
if (DEBUG) Log.d(TAG, "dark mode average: $value")
|
||||
|
||||
isDarkMode = value < darkModeThreshold
|
||||
}
|
||||
|
||||
// The latest bundle for calculating light mode claim.
|
||||
var bundleLightMode = ArrayList<Float>()
|
||||
set(value) {
|
||||
field = value
|
||||
|
||||
val average = value.average()
|
||||
|
||||
if (!average.isNaN()) {
|
||||
bundleAverageLightMode = average
|
||||
}
|
||||
}
|
||||
|
||||
// The latest bundle for calculating dark mode claim.
|
||||
var bundleDarkMode = ArrayList<Float>()
|
||||
set(value) {
|
||||
field = value
|
||||
|
||||
val average = value.average()
|
||||
|
||||
if (!average.isNaN()) {
|
||||
bundleAverageDarkMode = average
|
||||
}
|
||||
}
|
||||
|
||||
// The latest light level from light sensor event updates.
|
||||
var lightSensorLevel = 0.0f
|
||||
set(value) {
|
||||
field = value
|
||||
|
||||
bundlesQueueLightMode.forEach { bundle -> bundle.add(value) }
|
||||
bundlesQueueDarkMode.forEach { bundle -> bundle.add(value) }
|
||||
}
|
||||
|
||||
// Creates a new bundle that collects light sensor events for calculating the light mode claim,
|
||||
// and adds it to the end of the queue. It schedules a call to dequeue this bundle after
|
||||
// [LIGHT_SAMPLING_SPAN_MILLIS]. Once started, it also repeatedly calls itself at
|
||||
// [LIGHT_SAMPLING_FREQUENCY_MILLIS].
|
||||
val enqueueLightModeBundle: Runnable = object : Runnable {
|
||||
override fun run() {
|
||||
if (DEBUG) Log.d(TAG, "enqueueing a light mode bundle")
|
||||
|
||||
bundlesQueueLightMode.add(ArrayList())
|
||||
|
||||
executor.executeDelayed(dequeueLightModeBundle, lightSamplingSpanMillis.toLong())
|
||||
executor.executeDelayed(this, lightSamplingFrequencyMillis.toLong())
|
||||
}
|
||||
}
|
||||
|
||||
// Creates a new bundle that collects light sensor events for calculating the dark mode claim,
|
||||
// and adds it to the end of the queue. It schedules a call to dequeue this bundle after
|
||||
// [DARK_SAMPLING_SPAN_MILLIS]. Once started, it also repeatedly calls itself at
|
||||
// [DARK_SAMPLING_FREQUENCY_MILLIS].
|
||||
val enqueueDarkModeBundle: Runnable = object : Runnable {
|
||||
override fun run() {
|
||||
if (DEBUG) Log.d(TAG, "enqueueing a dark mode bundle")
|
||||
|
||||
bundlesQueueDarkMode.add(ArrayList())
|
||||
|
||||
executor.executeDelayed(dequeueDarkModeBundle, darkSamplingSpanMillis.toLong())
|
||||
executor.executeDelayed(this, darkSamplingFrequencyMillis.toLong())
|
||||
}
|
||||
}
|
||||
|
||||
// Collects the oldest bundle from the light mode bundles queue, and as a result triggering a
|
||||
// calculation of the light mode claim.
|
||||
val dequeueLightModeBundle: Runnable = object : Runnable {
|
||||
override fun run() {
|
||||
if (bundlesQueueLightMode.isEmpty()) return
|
||||
|
||||
bundleLightMode = bundlesQueueLightMode.removeAt(0)
|
||||
|
||||
if (DEBUG) Log.d(TAG, "dequeued a light mode bundle of size ${bundleLightMode.size}")
|
||||
}
|
||||
}
|
||||
|
||||
// Collects the oldest bundle from the dark mode bundles queue, and as a result triggering a
|
||||
// calculation of the dark mode claim.
|
||||
val dequeueDarkModeBundle: Runnable = object : Runnable {
|
||||
override fun run() {
|
||||
if (bundlesQueueDarkMode.isEmpty()) return
|
||||
|
||||
bundleDarkMode = bundlesQueueDarkMode.removeAt(0)
|
||||
|
||||
if (DEBUG) Log.d(TAG, "dequeued a dark mode bundle of size ${bundleDarkMode.size}")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the algorithm.
|
||||
*
|
||||
* @param callback callback that gets triggered when the ambient light mode changes.
|
||||
*/
|
||||
override fun start(callback: AmbientLightModeMonitor.Callback?) {
|
||||
if (DEBUG) Log.d(TAG, "start algorithm")
|
||||
|
||||
if (callback == null) {
|
||||
if (DEBUG) Log.w(TAG, "callback is null")
|
||||
return
|
||||
}
|
||||
|
||||
if (this.callback != null) {
|
||||
if (DEBUG) Log.w(TAG, "already started")
|
||||
return
|
||||
}
|
||||
|
||||
this.callback = callback
|
||||
|
||||
executor.execute(enqueueLightModeBundle)
|
||||
executor.execute(enqueueDarkModeBundle)
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop the algorithm.
|
||||
*/
|
||||
override fun stop() {
|
||||
if (DEBUG) Log.d(TAG, "stop algorithm")
|
||||
|
||||
if (callback == null) {
|
||||
if (DEBUG) Log.w(TAG, "haven't started")
|
||||
return
|
||||
}
|
||||
|
||||
callback = null
|
||||
|
||||
// Resets bundle queues.
|
||||
bundlesQueueLightMode.clear()
|
||||
bundlesQueueDarkMode.clear()
|
||||
|
||||
// Resets ambient light mode.
|
||||
mode = AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_UNDECIDED
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the light sensor event value.
|
||||
*
|
||||
* @param value light sensor update value.
|
||||
*/
|
||||
override fun onUpdateLightSensorEvent(value: Float) {
|
||||
if (callback == null) {
|
||||
if (DEBUG) Log.w(TAG, "ignore light sensor event because algorithm not started")
|
||||
return
|
||||
}
|
||||
|
||||
lightSensorLevel = value
|
||||
}
|
||||
}
|
||||
@@ -1,38 +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.dagger;
|
||||
|
||||
import com.android.systemui.idle.IdleHostView;
|
||||
import com.android.systemui.idle.IdleHostViewController;
|
||||
|
||||
import dagger.BindsInstance;
|
||||
import dagger.Subcomponent;
|
||||
|
||||
/**
|
||||
* Subcomponent for working with {@link IdleHostView}.
|
||||
*/
|
||||
@Subcomponent
|
||||
public interface IdleViewComponent {
|
||||
/** Simple factory for {@link Factory}. */
|
||||
@Subcomponent.Factory
|
||||
interface Factory {
|
||||
IdleViewComponent build(@BindsInstance IdleHostView idleHostView);
|
||||
}
|
||||
|
||||
/** Builds a {@link IdleHostViewController}. */
|
||||
IdleHostViewController getIdleHostViewController();
|
||||
}
|
||||
@@ -135,9 +135,6 @@ import com.android.systemui.flags.FeatureFlags;
|
||||
import com.android.systemui.flags.Flags;
|
||||
import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
|
||||
import com.android.systemui.fragments.FragmentService;
|
||||
import com.android.systemui.idle.IdleHostView;
|
||||
import com.android.systemui.idle.IdleHostViewController;
|
||||
import com.android.systemui.idle.dagger.IdleViewComponent;
|
||||
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
|
||||
import com.android.systemui.media.KeyguardMediaController;
|
||||
import com.android.systemui.media.MediaDataManager;
|
||||
@@ -322,7 +319,6 @@ public class NotificationPanelViewController extends PanelViewController
|
||||
private final KeyguardQsUserSwitchComponent.Factory mKeyguardQsUserSwitchComponentFactory;
|
||||
private final KeyguardUserSwitcherComponent.Factory mKeyguardUserSwitcherComponentFactory;
|
||||
private final KeyguardStatusBarViewComponent.Factory mKeyguardStatusBarViewComponentFactory;
|
||||
private final IdleViewComponent.Factory mIdleViewComponentFactory;
|
||||
private final FragmentService mFragmentService;
|
||||
private final ScrimController mScrimController;
|
||||
private final PrivacyDotViewController mPrivacyDotViewController;
|
||||
@@ -356,8 +352,6 @@ public class NotificationPanelViewController extends PanelViewController
|
||||
@Nullable
|
||||
private CommunalHostViewController mCommunalViewController;
|
||||
private KeyguardStatusViewController mKeyguardStatusViewController;
|
||||
@Nullable
|
||||
private IdleHostViewController mIdleHostViewController;
|
||||
private LockIconViewController mLockIconViewController;
|
||||
private NotificationsQuickSettingsContainer mNotificationContainerParent;
|
||||
private NotificationsQSContainerController mNotificationsQSContainerController;
|
||||
@@ -369,7 +363,6 @@ public class NotificationPanelViewController extends PanelViewController
|
||||
private VelocityTracker mQsVelocityTracker;
|
||||
private boolean mQsTracking;
|
||||
|
||||
private IdleHostView mIdleHostView;
|
||||
private CommunalHostView mCommunalView;
|
||||
|
||||
/**
|
||||
@@ -768,7 +761,6 @@ public class NotificationPanelViewController extends PanelViewController
|
||||
KeyguardUserSwitcherComponent.Factory keyguardUserSwitcherComponentFactory,
|
||||
KeyguardStatusBarViewComponent.Factory keyguardStatusBarViewComponentFactory,
|
||||
CommunalViewComponent.Factory communalViewComponentFactory,
|
||||
IdleViewComponent.Factory idleViewComponentFactory,
|
||||
LockscreenShadeTransitionController lockscreenShadeTransitionController,
|
||||
NotificationGroupManagerLegacy groupManager,
|
||||
NotificationIconAreaController notificationIconAreaController,
|
||||
@@ -839,7 +831,6 @@ public class NotificationPanelViewController extends PanelViewController
|
||||
mCommunalViewComponentFactory = communalViewComponentFactory;
|
||||
mKeyguardStatusViewComponentFactory = keyguardStatusViewComponentFactory;
|
||||
mKeyguardStatusBarViewComponentFactory = keyguardStatusBarViewComponentFactory;
|
||||
mIdleViewComponentFactory = idleViewComponentFactory;
|
||||
mDepthController = notificationShadeDepthController;
|
||||
mContentResolver = contentResolver;
|
||||
mKeyguardQsUserSwitchComponentFactory = keyguardQsUserSwitchComponentFactory;
|
||||
@@ -966,7 +957,6 @@ public class NotificationPanelViewController extends PanelViewController
|
||||
private void onFinishInflate() {
|
||||
loadDimens();
|
||||
mKeyguardStatusBar = mView.findViewById(R.id.keyguard_header);
|
||||
mIdleHostView = mView.findViewById(R.id.idle_host_view);
|
||||
mCommunalView = mView.findViewById(R.id.communal_host);
|
||||
|
||||
FrameLayout userAvatarContainer = null;
|
||||
@@ -989,12 +979,6 @@ public class NotificationPanelViewController extends PanelViewController
|
||||
.getKeyguardStatusBarViewController();
|
||||
mKeyguardStatusBarViewController.init();
|
||||
|
||||
if (mIdleHostView != null) {
|
||||
IdleViewComponent idleViewComponent = mIdleViewComponentFactory.build(mIdleHostView);
|
||||
mIdleHostViewController = idleViewComponent.getIdleHostViewController();
|
||||
mIdleHostViewController.init();
|
||||
}
|
||||
|
||||
if (mCommunalView != null) {
|
||||
CommunalViewComponent communalViewComponent =
|
||||
mCommunalViewComponentFactory.build(mCommunalView);
|
||||
@@ -1008,7 +992,6 @@ public class NotificationPanelViewController extends PanelViewController
|
||||
mView.findViewById(R.id.keyguard_status_view),
|
||||
userAvatarContainer,
|
||||
keyguardUserSwitcherView,
|
||||
mIdleHostView,
|
||||
mCommunalView);
|
||||
|
||||
NotificationStackScrollLayout stackScrollLayout = mView.findViewById(
|
||||
@@ -1101,7 +1084,6 @@ public class NotificationPanelViewController extends PanelViewController
|
||||
private void updateViewControllers(KeyguardStatusView keyguardStatusView,
|
||||
FrameLayout userAvatarView,
|
||||
KeyguardUserSwitcherView keyguardUserSwitcherView,
|
||||
IdleHostView idleHostView,
|
||||
CommunalHostView communalView) {
|
||||
// Re-associate the KeyguardStatusViewController
|
||||
KeyguardStatusViewComponent statusViewComponent =
|
||||
@@ -1109,13 +1091,6 @@ public class NotificationPanelViewController extends PanelViewController
|
||||
mKeyguardStatusViewController = statusViewComponent.getKeyguardStatusViewController();
|
||||
mKeyguardStatusViewController.init();
|
||||
|
||||
if (idleHostView != null && idleHostView != mIdleHostView) {
|
||||
mIdleHostView = idleHostView;
|
||||
IdleViewComponent idleViewComponent = mIdleViewComponentFactory.build(idleHostView);
|
||||
mIdleHostViewController = idleViewComponent.getIdleHostViewController();
|
||||
mIdleHostViewController.init();
|
||||
}
|
||||
|
||||
if (mKeyguardUserSwitcherController != null) {
|
||||
// Try to close the switcher so that callbacks are triggered if necessary.
|
||||
// Otherwise, NPV can get into a state where some of the views are still hidden
|
||||
@@ -1287,7 +1262,7 @@ public class NotificationPanelViewController extends PanelViewController
|
||||
showKeyguardUserSwitcher /* enabled */);
|
||||
|
||||
updateViewControllers(mView.findViewById(R.id.keyguard_status_view), userAvatarView,
|
||||
keyguardUserSwitcherView, mView.findViewById(R.id.idle_host_view), mCommunalView);
|
||||
keyguardUserSwitcherView, mCommunalView);
|
||||
|
||||
// Update keyguard bottom area
|
||||
int index = mView.indexOfChild(mKeyguardBottomArea);
|
||||
|
||||
@@ -1,111 +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.hardware.Sensor
|
||||
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.mock
|
||||
import org.mockito.Mockito.anyInt
|
||||
import org.mockito.Mockito.any
|
||||
import org.mockito.Mockito.eq
|
||||
import org.mockito.Mockito.never
|
||||
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
|
||||
@Mock private lateinit var algorithm: AmbientLightModeMonitor.DebounceAlgorithm
|
||||
|
||||
private lateinit var ambientLightModeMonitor: AmbientLightModeMonitor
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
MockitoAnnotations.initMocks(this)
|
||||
|
||||
`when`(sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT)).thenReturn(sensor)
|
||||
|
||||
ambientLightModeMonitor = AmbientLightModeMonitor(algorithm, sensorManager)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldRegisterSensorEventListenerOnStart() {
|
||||
val callback = mock(AmbientLightModeMonitor.Callback::class.java)
|
||||
ambientLightModeMonitor.start(callback)
|
||||
|
||||
verify(sensorManager).registerListener(any(), eq(sensor), anyInt())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldUnregisterSensorEventListenerOnStop() {
|
||||
val callback = mock(AmbientLightModeMonitor.Callback::class.java)
|
||||
ambientLightModeMonitor.start(callback)
|
||||
|
||||
val sensorEventListener = captureSensorEventListener()
|
||||
|
||||
ambientLightModeMonitor.stop()
|
||||
|
||||
verify(sensorManager).unregisterListener(eq(sensorEventListener))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldStartDebounceAlgorithmOnStart() {
|
||||
val callback = mock(AmbientLightModeMonitor.Callback::class.java)
|
||||
ambientLightModeMonitor.start(callback)
|
||||
|
||||
verify(algorithm).start(eq(callback))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldStopDebounceAlgorithmOnStop() {
|
||||
val callback = mock(AmbientLightModeMonitor.Callback::class.java)
|
||||
ambientLightModeMonitor.start(callback)
|
||||
ambientLightModeMonitor.stop()
|
||||
|
||||
verify(algorithm).stop()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldNotRegisterForSensorUpdatesIfSensorNotAvailable() {
|
||||
`when`(sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT)).thenReturn(null)
|
||||
val ambientLightModeMonitor = AmbientLightModeMonitor(algorithm, sensorManager)
|
||||
|
||||
val callback = mock(AmbientLightModeMonitor.Callback::class.java)
|
||||
ambientLightModeMonitor.start(callback)
|
||||
|
||||
verify(sensorManager, never()).registerListener(any(), any(Sensor::class.java), anyInt())
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
}
|
||||
@@ -1,137 +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 static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
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.res.Resources;
|
||||
import android.os.PowerManager;
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
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.statusbar.policy.KeyguardStateController;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import javax.inject.Provider;
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner.class)
|
||||
public class IdleHostViewControllerTest extends SysuiTestCase {
|
||||
@Mock private BroadcastDispatcher mBroadcastDispatcher;
|
||||
@Mock private PowerManager mPowerManager;
|
||||
@Mock private IdleHostView mIdleHostView;
|
||||
@Mock private Resources mResources;
|
||||
@Mock private Provider<View> mViewProvider;
|
||||
@Mock private KeyguardStateController mKeyguardStateController;
|
||||
@Mock private StatusBarStateController mStatusBarStateController;
|
||||
@Mock private AmbientLightModeMonitor mAmbientLightModeMonitor;
|
||||
|
||||
private KeyguardStateController.Callback mKeyguardStateCallback;
|
||||
private StatusBarStateController.StateListener mStatusBarStateListener;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
when(mResources.getBoolean(R.bool.config_enableIdleMode)).thenReturn(true);
|
||||
when(mStatusBarStateController.isDozing()).thenReturn(false);
|
||||
|
||||
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 =
|
||||
ArgumentCaptor.forClass(KeyguardStateController.Callback.class);
|
||||
verify(mKeyguardStateController).addCallback(keyguardStateCallbackCaptor.capture());
|
||||
mKeyguardStateCallback = keyguardStateCallbackCaptor.getValue();
|
||||
|
||||
// Captures status bar state listener.
|
||||
ArgumentCaptor<StatusBarStateController.StateListener> statusBarStateListenerCaptor =
|
||||
ArgumentCaptor.forClass(StatusBarStateController.StateListener.class);
|
||||
verify(mStatusBarStateController).addCallback(statusBarStateListenerCaptor.capture());
|
||||
mStatusBarStateListener = statusBarStateListenerCaptor.getValue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStartDozingWhenLowLight() {
|
||||
// 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.
|
||||
lightMonitorCallback.onChange(AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_DARK);
|
||||
|
||||
// Verifies it goes to sleep.
|
||||
verify(mPowerManager).goToSleep(anyLong(), anyInt(), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWakeUpWhenRegularLight() {
|
||||
// Keyguard showing.
|
||||
when(mKeyguardStateController.isShowing()).thenReturn(true);
|
||||
mKeyguardStateCallback.onKeyguardShowingChanged();
|
||||
|
||||
// In low light / dozing.
|
||||
final AmbientLightModeMonitor.Callback lightMonitorCallback =
|
||||
captureAmbientLightModeMonitorCallback();
|
||||
lightMonitorCallback.onChange(AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_DARK);
|
||||
mStatusBarStateListener.onDozingChanged(true /*isDozing*/);
|
||||
|
||||
// Regular ambient lighting.
|
||||
lightMonitorCallback.onChange(AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_LIGHT);
|
||||
|
||||
// Verifies it wakes up from sleep.
|
||||
verify(mPowerManager).wakeUp(anyLong(), anyInt(), anyString());
|
||||
}
|
||||
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
@@ -1,358 +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.res.Resources
|
||||
import android.testing.AndroidTestingRunner
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.util.concurrency.FakeExecutor
|
||||
import com.android.systemui.util.time.FakeSystemClock
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.Mock
|
||||
import org.mockito.MockitoAnnotations
|
||||
import org.mockito.Mockito.mock
|
||||
import org.mockito.Mockito.never
|
||||
import org.mockito.Mockito.verify
|
||||
import org.mockito.Mockito.reset
|
||||
import org.mockito.Mockito.`when`
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner::class)
|
||||
class LightSensorDebounceAlgorithmTest : SysuiTestCase() {
|
||||
@Mock private lateinit var resources: Resources
|
||||
|
||||
private val systemClock = FakeSystemClock()
|
||||
private val executor = FakeExecutor(systemClock)
|
||||
|
||||
private lateinit var algorithm: LightSensorEventsDebounceAlgorithm
|
||||
|
||||
private val mockLightModeThreshold = 5
|
||||
private val mockDarkModeThreshold = 2
|
||||
private val mockLightModeSpan = 100
|
||||
private val mockDarkModeSpan = 50
|
||||
private val mockLightModeFrequency = 10
|
||||
private val mockDarkModeFrequency = 5
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
MockitoAnnotations.initMocks(this)
|
||||
|
||||
`when`(resources.getInteger(R.integer.config_ambientLightModeThreshold))
|
||||
.thenReturn(mockLightModeThreshold)
|
||||
`when`(resources.getInteger(R.integer.config_ambientDarkModeThreshold))
|
||||
.thenReturn(mockDarkModeThreshold)
|
||||
`when`(resources.getInteger(R.integer.config_ambientLightModeSamplingSpanMillis))
|
||||
.thenReturn(mockLightModeSpan)
|
||||
`when`(resources.getInteger(R.integer.config_ambientDarkModeSamplingSpanMillis))
|
||||
.thenReturn(mockDarkModeSpan)
|
||||
`when`(resources.getInteger(R.integer.config_ambientLightModeSamplingFrequencyMillis))
|
||||
.thenReturn(mockLightModeFrequency)
|
||||
`when`(resources.getInteger(R.integer.config_ambientDarkModeSamplingFrequencyMillis))
|
||||
.thenReturn(mockDarkModeFrequency)
|
||||
|
||||
algorithm = LightSensorEventsDebounceAlgorithm(executor, resources)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldOnlyTriggerCallbackWhenValueChanges() {
|
||||
val callback = mock(AmbientLightModeMonitor.Callback::class.java)
|
||||
algorithm.start(callback)
|
||||
|
||||
// Light mode, should trigger callback.
|
||||
algorithm.mode = AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_LIGHT
|
||||
verify(callback).onChange(AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_LIGHT)
|
||||
reset(callback)
|
||||
|
||||
// Light mode again, should NOT trigger callback.
|
||||
algorithm.mode = AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_LIGHT
|
||||
verify(callback, never()).onChange(AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_LIGHT)
|
||||
reset(callback)
|
||||
|
||||
// Dark mode, should trigger callback.
|
||||
algorithm.mode = AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_DARK
|
||||
verify(callback).onChange(AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_DARK)
|
||||
reset(callback)
|
||||
|
||||
// Dark mode again, should not trigger callback.
|
||||
algorithm.mode = AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_DARK
|
||||
verify(callback, never()).onChange(AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_DARK)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldReportUndecidedWhenNeitherLightNorDarkClaimIsTrue() {
|
||||
algorithm.isDarkMode = false
|
||||
algorithm.isLightMode = false
|
||||
|
||||
assertThat(algorithm.mode).isEqualTo(
|
||||
AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_UNDECIDED)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldReportDarkModeAsLongAsDarkModeClaimIsTrue() {
|
||||
algorithm.isDarkMode = true
|
||||
algorithm.isLightMode = false
|
||||
|
||||
assertThat(algorithm.mode).isEqualTo(
|
||||
AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_DARK)
|
||||
|
||||
algorithm.isLightMode = true
|
||||
assertThat(algorithm.mode).isEqualTo(
|
||||
AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_DARK)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldReportLightModeWhenLightModeClaimIsTrueAndDarkModeClaimIsFalse() {
|
||||
algorithm.isLightMode = true
|
||||
algorithm.isDarkMode = false
|
||||
|
||||
assertThat(algorithm.mode).isEqualTo(
|
||||
AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_LIGHT)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldSetIsLightModeToTrueWhenBundleAverageIsGreaterThanThreshold() {
|
||||
// Note: [mockLightModeThreshold] is 5.0.
|
||||
algorithm.bundleAverageLightMode = 5.1
|
||||
assertThat(algorithm.isLightMode).isTrue()
|
||||
|
||||
algorithm.bundleAverageLightMode = 10.0
|
||||
assertThat(algorithm.isLightMode).isTrue()
|
||||
|
||||
algorithm.bundleAverageLightMode = 20.0
|
||||
assertThat(algorithm.isLightMode).isTrue()
|
||||
|
||||
algorithm.bundleAverageLightMode = 5.0
|
||||
assertThat(algorithm.isLightMode).isFalse()
|
||||
|
||||
algorithm.bundleAverageLightMode = 3.0
|
||||
assertThat(algorithm.isLightMode).isFalse()
|
||||
|
||||
algorithm.bundleAverageLightMode = 0.0
|
||||
assertThat(algorithm.isLightMode).isFalse()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldSetIsDarkModeToTrueWhenBundleAverageIsLessThanThreshold() {
|
||||
// Note: [mockDarkModeThreshold] is 2.0.
|
||||
algorithm.bundleAverageDarkMode = 1.9
|
||||
assertThat(algorithm.isDarkMode).isTrue()
|
||||
|
||||
algorithm.bundleAverageDarkMode = 1.0
|
||||
assertThat(algorithm.isDarkMode).isTrue()
|
||||
|
||||
algorithm.bundleAverageDarkMode = 0.0
|
||||
assertThat(algorithm.isDarkMode).isTrue()
|
||||
|
||||
algorithm.bundleAverageDarkMode = 2.0
|
||||
assertThat(algorithm.isDarkMode).isFalse()
|
||||
|
||||
algorithm.bundleAverageDarkMode = 3.0
|
||||
assertThat(algorithm.isDarkMode).isFalse()
|
||||
|
||||
algorithm.bundleAverageDarkMode = 10.0
|
||||
assertThat(algorithm.isDarkMode).isFalse()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldCorrectlyCalculateAverageFromABundle() {
|
||||
// For light mode.
|
||||
algorithm.bundleLightMode = arrayListOf(1.0f, 3.0f, 5.0f, 7.0f)
|
||||
assertThat(algorithm.bundleAverageLightMode).isEqualTo(4.0)
|
||||
|
||||
algorithm.bundleLightMode = arrayListOf(2.0f, 4.0f, 6.0f, 8.0f)
|
||||
assertThat(algorithm.bundleAverageLightMode).isEqualTo(5.0)
|
||||
|
||||
// For dark mode.
|
||||
algorithm.bundleDarkMode = arrayListOf(1.0f, 3.0f, 5.0f, 7.0f, 9.0f)
|
||||
assertThat(algorithm.bundleAverageDarkMode).isEqualTo(5.0)
|
||||
|
||||
algorithm.bundleDarkMode = arrayListOf(2.0f, 4.0f, 6.0f, 8.0f, 10.0f)
|
||||
assertThat(algorithm.bundleAverageDarkMode).isEqualTo(6.0)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldAddSensorEventUpdatesToBundles() {
|
||||
val callback = mock(AmbientLightModeMonitor.Callback::class.java)
|
||||
// On start() one bundle is created for light and dark mode each.
|
||||
algorithm.start(callback)
|
||||
executor.runAllReady()
|
||||
|
||||
// Add 1 more bundle to queue for each mode.
|
||||
algorithm.bundlesQueueLightMode.add(ArrayList())
|
||||
algorithm.bundlesQueueDarkMode.add(ArrayList())
|
||||
|
||||
algorithm.onUpdateLightSensorEvent(1.0f)
|
||||
algorithm.onUpdateLightSensorEvent(1.0f)
|
||||
algorithm.onUpdateLightSensorEvent(2.0f)
|
||||
algorithm.onUpdateLightSensorEvent(3.0f)
|
||||
algorithm.onUpdateLightSensorEvent(4.0f)
|
||||
|
||||
val expectedValues = listOf(1.0f, 1.0f, 2.0f, 3.0f, 4.0f)
|
||||
|
||||
assertBundleContainsAll(algorithm.bundlesQueueLightMode[0], expectedValues)
|
||||
assertBundleContainsAll(algorithm.bundlesQueueLightMode[1], expectedValues)
|
||||
assertBundleContainsAll(algorithm.bundlesQueueDarkMode[0], expectedValues)
|
||||
assertBundleContainsAll(algorithm.bundlesQueueDarkMode[1], expectedValues)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldCorrectlyEnqueueLightModeBundles() {
|
||||
assertThat(algorithm.bundlesQueueLightMode.size).isEqualTo(0)
|
||||
|
||||
algorithm.enqueueLightModeBundle.run()
|
||||
assertThat(algorithm.bundlesQueueLightMode.size).isEqualTo(1)
|
||||
|
||||
algorithm.enqueueLightModeBundle.run()
|
||||
assertThat(algorithm.bundlesQueueLightMode.size).isEqualTo(2)
|
||||
|
||||
algorithm.enqueueLightModeBundle.run()
|
||||
assertThat(algorithm.bundlesQueueLightMode.size).isEqualTo(3)
|
||||
|
||||
// Verifies dark mode bundles queue is not impacted.
|
||||
assertThat(algorithm.bundlesQueueDarkMode.size).isEqualTo(0)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldCorrectlyEnqueueDarkModeBundles() {
|
||||
assertThat(algorithm.bundlesQueueDarkMode.size).isEqualTo(0)
|
||||
|
||||
algorithm.enqueueDarkModeBundle.run()
|
||||
assertThat(algorithm.bundlesQueueDarkMode.size).isEqualTo(1)
|
||||
|
||||
algorithm.enqueueDarkModeBundle.run()
|
||||
assertThat(algorithm.bundlesQueueDarkMode.size).isEqualTo(2)
|
||||
|
||||
algorithm.enqueueDarkModeBundle.run()
|
||||
assertThat(algorithm.bundlesQueueDarkMode.size).isEqualTo(3)
|
||||
|
||||
// Verifies light mode bundles queue is not impacted.
|
||||
assertThat(algorithm.bundlesQueueLightMode.size).isEqualTo(0)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldCorrectlyDequeueLightModeBundles() {
|
||||
// Sets up the light mode bundles queue.
|
||||
val bundle1 = arrayListOf(1.0f, 3.0f, 6.0f, 9.0f)
|
||||
val bundle2 = arrayListOf(5.0f, 10f)
|
||||
val bundle3 = arrayListOf(2.0f, 4.0f)
|
||||
algorithm.bundlesQueueLightMode.add(bundle1)
|
||||
algorithm.bundlesQueueLightMode.add(bundle2)
|
||||
algorithm.bundlesQueueLightMode.add(bundle3)
|
||||
|
||||
// The committed bundle should be the first one in queue.
|
||||
algorithm.dequeueLightModeBundle.run()
|
||||
assertBundleContainsAll(algorithm.bundleLightMode, bundle1)
|
||||
|
||||
algorithm.dequeueLightModeBundle.run()
|
||||
assertBundleContainsAll(algorithm.bundleLightMode, bundle2)
|
||||
|
||||
algorithm.dequeueLightModeBundle.run()
|
||||
assertBundleContainsAll(algorithm.bundleLightMode, bundle3)
|
||||
|
||||
// Verifies that the dark mode bundle is not impacted.
|
||||
assertBundleContainsAll(algorithm.bundleDarkMode, listOf())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldCorrectlyDequeueDarkModeBundles() {
|
||||
// Sets up the dark mode bundles queue.
|
||||
val bundle1 = arrayListOf(2.0f, 4.0f)
|
||||
val bundle2 = arrayListOf(5.0f, 10f)
|
||||
val bundle3 = arrayListOf(1.0f, 3.0f, 6.0f, 9.0f)
|
||||
algorithm.bundlesQueueDarkMode.add(bundle1)
|
||||
algorithm.bundlesQueueDarkMode.add(bundle2)
|
||||
algorithm.bundlesQueueDarkMode.add(bundle3)
|
||||
|
||||
// The committed bundle should be the first one in queue.
|
||||
algorithm.dequeueDarkModeBundle.run()
|
||||
assertBundleContainsAll(algorithm.bundleDarkMode, bundle1)
|
||||
|
||||
algorithm.dequeueDarkModeBundle.run()
|
||||
assertBundleContainsAll(algorithm.bundleDarkMode, bundle2)
|
||||
|
||||
algorithm.dequeueDarkModeBundle.run()
|
||||
assertBundleContainsAll(algorithm.bundleDarkMode, bundle3)
|
||||
|
||||
// Verifies that the light mode bundle is not impacted.
|
||||
assertBundleContainsAll(algorithm.bundleLightMode, listOf())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldSetLightSensorLevelFromSensorEventUpdates() {
|
||||
val callback = mock(AmbientLightModeMonitor.Callback::class.java)
|
||||
algorithm.start(callback)
|
||||
|
||||
algorithm.onUpdateLightSensorEvent(1.0f)
|
||||
assertThat(algorithm.lightSensorLevel).isEqualTo(1.0f)
|
||||
|
||||
algorithm.onUpdateLightSensorEvent(10.0f)
|
||||
assertThat(algorithm.lightSensorLevel).isEqualTo(10.0f)
|
||||
|
||||
algorithm.onUpdateLightSensorEvent(0.0f)
|
||||
assertThat(algorithm.lightSensorLevel).isEqualTo(0.0f)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldRippleFromSensorEventUpdatesDownToAmbientLightMode() {
|
||||
val callback = mock(AmbientLightModeMonitor.Callback::class.java)
|
||||
algorithm.start(callback)
|
||||
executor.runAllReady()
|
||||
|
||||
// Sensor event updates.
|
||||
algorithm.onUpdateLightSensorEvent(10.0f)
|
||||
algorithm.onUpdateLightSensorEvent(15.0f)
|
||||
algorithm.onUpdateLightSensorEvent(12.0f)
|
||||
algorithm.onUpdateLightSensorEvent(10.0f)
|
||||
|
||||
// Advances time so both light and dark claims have been calculated.
|
||||
systemClock.advanceTime((mockLightModeSpan + 1).toLong())
|
||||
|
||||
// Verifies the callback is triggered the ambient mode has changed LIGHT.
|
||||
verify(callback).onChange(AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_LIGHT)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldRippleFromSensorEventUpdatesDownToAmbientDarkMode() {
|
||||
val callback = mock(AmbientLightModeMonitor.Callback::class.java)
|
||||
algorithm.start(callback)
|
||||
executor.runAllReady()
|
||||
|
||||
// Sensor event updates.
|
||||
algorithm.onUpdateLightSensorEvent(1.0f)
|
||||
algorithm.onUpdateLightSensorEvent(0.5f)
|
||||
algorithm.onUpdateLightSensorEvent(1.2f)
|
||||
algorithm.onUpdateLightSensorEvent(0.8f)
|
||||
|
||||
// Advances time so both light and dark claims have been calculated.
|
||||
systemClock.advanceTime((mockLightModeSpan + 1).toLong())
|
||||
|
||||
// Verifies the callback is triggered the ambient mode has changed DARK.
|
||||
verify(callback).onChange(AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_DARK)
|
||||
}
|
||||
|
||||
// Asserts that [bundle] contains the same elements as [expected], not necessarily in the same
|
||||
// order.
|
||||
private fun assertBundleContainsAll(bundle: ArrayList<Float>, expected: Collection<Float>) {
|
||||
assertThat(bundle.size).isEqualTo(expected.size)
|
||||
assertThat(bundle.containsAll(expected))
|
||||
}
|
||||
}
|
||||
@@ -100,8 +100,6 @@ import com.android.systemui.dump.DumpManager;
|
||||
import com.android.systemui.flags.FeatureFlags;
|
||||
import com.android.systemui.fragments.FragmentHostManager;
|
||||
import com.android.systemui.fragments.FragmentService;
|
||||
import com.android.systemui.idle.IdleHostViewController;
|
||||
import com.android.systemui.idle.dagger.IdleViewComponent;
|
||||
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
|
||||
import com.android.systemui.media.KeyguardMediaController;
|
||||
import com.android.systemui.media.MediaDataManager;
|
||||
@@ -266,12 +264,6 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
|
||||
@Mock
|
||||
private KeyguardUserSwitcherController mKeyguardUserSwitcherController;
|
||||
@Mock
|
||||
private IdleViewComponent.Factory mIdleViewComponentFactory;
|
||||
@Mock
|
||||
private IdleViewComponent mIdleViewComponent;
|
||||
@Mock
|
||||
private IdleHostViewController mIdleHostViewController;
|
||||
@Mock
|
||||
private KeyguardStatusViewComponent mKeyguardStatusViewComponent;
|
||||
@Mock
|
||||
private KeyguardStatusBarViewComponent.Factory mKeyguardStatusBarViewComponentFactory;
|
||||
@@ -475,10 +467,6 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
|
||||
.thenReturn(mCommunalViewComponent);
|
||||
when(mCommunalViewComponent.getCommunalHostViewController())
|
||||
.thenReturn(mCommunalHostViewController);
|
||||
when(mIdleViewComponentFactory.build(any()))
|
||||
.thenReturn(mIdleViewComponent);
|
||||
when(mIdleViewComponent.getIdleHostViewController())
|
||||
.thenReturn(mIdleHostViewController);
|
||||
when(mLayoutInflater.inflate(eq(R.layout.keyguard_status_view), any(), anyBoolean()))
|
||||
.thenReturn(mKeyguardStatusView);
|
||||
when(mLayoutInflater.inflate(eq(R.layout.keyguard_user_switcher), any(), anyBoolean()))
|
||||
@@ -523,7 +511,6 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
|
||||
mKeyguardUserSwitcherComponentFactory,
|
||||
mKeyguardStatusBarViewComponentFactory,
|
||||
mCommunalViewComponentFactory,
|
||||
mIdleViewComponentFactory,
|
||||
mLockscreenShadeTransitionController,
|
||||
mGroupManager,
|
||||
mNotificationAreaController,
|
||||
|
||||
Reference in New Issue
Block a user