summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author William Xiao <wxyz@google.com> 2025-02-07 09:54:14 -0800
committer William Xiao <wxyz@google.com> 2025-02-07 16:57:10 -0800
commit4f9ab76ab6c9aea09d554fc56e09e905c739114b (patch)
treef820ed5460f735a992aa6ecd9ec5a66dfe4e8a87
parentf13b68f131965dc048f0c17a1b671419744f079e (diff)
Fix low light triggering on phones when entering doze
Tangor did not have doze/aod so it was not accounted for in the conditions. While DreamManager does explicitly not override doze with the system dream, the doze dream does not start dozing fast enough to prevent the low light code from overriding it with the system dream. This change adjusts the DeviceInactiveCondition to only be true if the device is not dozing or entering dozing to prevent the possibility of entering low light dream when unplugged and entering aod. Bug: 394707567 Fixes: 394707567 Flag: com.android.systemui.glanceable_hub_v2 Test: atest DeviceInactiveConditionTest manually verified on device in dark environment Change-Id: I83f9584940ab3e8a70125ad9dd050e77810465f4
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/communal/DeviceInactiveConditionTest.kt100
-rw-r--r--packages/SystemUI/src/com/android/systemui/communal/DeviceInactiveCondition.java31
-rw-r--r--packages/SystemUI/src/com/android/systemui/lowlightclock/dagger/LowLightModule.java2
3 files changed, 124 insertions, 9 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/DeviceInactiveConditionTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/DeviceInactiveConditionTest.kt
new file mode 100644
index 000000000000..0c97750ba281
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/DeviceInactiveConditionTest.kt
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2025 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.communal
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.keyguard.keyguardUpdateMonitor
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.keyguard.WakefulnessLifecycle
+import com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_ASLEEP
+import com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWAKE
+import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
+import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
+import com.android.systemui.keyguard.shared.model.DozeStateModel
+import com.android.systemui.keyguard.shared.model.DozeTransitionModel
+import com.android.systemui.keyguard.wakefulnessLifecycle
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.applicationCoroutineScope
+import com.android.systemui.kosmos.runTest
+import com.android.systemui.kosmos.useUnconfinedTestDispatcher
+import com.android.systemui.statusbar.policy.keyguardStateController
+import com.android.systemui.testKosmos
+import com.android.systemui.util.kotlin.JavaAdapter
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.kotlin.argumentCaptor
+import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.verify
+import org.mockito.kotlin.whenever
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class DeviceInactiveConditionTest : SysuiTestCase() {
+ private val kosmos =
+ testKosmos().useUnconfinedTestDispatcher().also {
+ whenever(it.wakefulnessLifecycle.wakefulness) doReturn WAKEFULNESS_AWAKE
+ }
+
+ private val Kosmos.underTest by
+ Kosmos.Fixture {
+ DeviceInactiveCondition(
+ applicationCoroutineScope,
+ keyguardStateController,
+ wakefulnessLifecycle,
+ keyguardUpdateMonitor,
+ keyguardInteractor,
+ JavaAdapter(applicationCoroutineScope),
+ )
+ }
+
+ @Test
+ fun asleep_conditionTrue() =
+ kosmos.runTest {
+ // Condition is false to start.
+ underTest.start()
+ assertThat(underTest.isConditionMet).isFalse()
+
+ // Condition is true when device goes to sleep.
+ sleep()
+ assertThat(underTest.isConditionMet).isTrue()
+ }
+
+ @Test
+ fun dozingAndAsleep_conditionFalse() =
+ kosmos.runTest {
+ // Condition is true when device is asleep.
+ underTest.start()
+ sleep()
+ assertThat(underTest.isConditionMet).isTrue()
+
+ // Condition turns false after doze starts.
+ fakeKeyguardRepository.setDozeTransitionModel(
+ DozeTransitionModel(from = DozeStateModel.UNINITIALIZED, to = DozeStateModel.DOZE)
+ )
+ assertThat(underTest.isConditionMet).isFalse()
+ }
+
+ fun Kosmos.sleep() {
+ whenever(wakefulnessLifecycle.wakefulness) doReturn WAKEFULNESS_ASLEEP
+ argumentCaptor<WakefulnessLifecycle.Observer>().apply {
+ verify(wakefulnessLifecycle).addObserver(capture())
+ firstValue.onStartedGoingToSleep()
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/DeviceInactiveCondition.java b/packages/SystemUI/src/com/android/systemui/communal/DeviceInactiveCondition.java
index 2e1b5ad177b5..e456310febfd 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/DeviceInactiveCondition.java
+++ b/packages/SystemUI/src/com/android/systemui/communal/DeviceInactiveCondition.java
@@ -17,16 +17,19 @@
package com.android.systemui.communal;
import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_ASLEEP;
-import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.dagger.qualifiers.Application;
import com.android.systemui.keyguard.WakefulnessLifecycle;
+import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
+import com.android.systemui.keyguard.shared.model.DozeStateModel;
import com.android.systemui.shared.condition.Condition;
import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.util.kotlin.JavaAdapter;
import kotlinx.coroutines.CoroutineScope;
+import kotlinx.coroutines.Job;
import javax.inject.Inject;
@@ -38,6 +41,10 @@ public class DeviceInactiveCondition extends Condition {
private final KeyguardStateController mKeyguardStateController;
private final WakefulnessLifecycle mWakefulnessLifecycle;
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+ private final KeyguardInteractor mKeyguardInteractor;
+ private final JavaAdapter mJavaAdapter;
+ private Job mAnyDozeListenerJob;
+ private boolean mAnyDoze;
private final KeyguardStateController.Callback mKeyguardStateCallback =
new KeyguardStateController.Callback() {
@Override
@@ -63,12 +70,14 @@ public class DeviceInactiveCondition extends Condition {
@Inject
public DeviceInactiveCondition(@Application CoroutineScope scope,
KeyguardStateController keyguardStateController,
- WakefulnessLifecycle wakefulnessLifecycle,
- KeyguardUpdateMonitor keyguardUpdateMonitor) {
+ WakefulnessLifecycle wakefulnessLifecycle, KeyguardUpdateMonitor keyguardUpdateMonitor,
+ KeyguardInteractor keyguardInteractor, JavaAdapter javaAdapter) {
super(scope);
mKeyguardStateController = keyguardStateController;
mWakefulnessLifecycle = wakefulnessLifecycle;
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
+ mKeyguardInteractor = keyguardInteractor;
+ mJavaAdapter = javaAdapter;
}
@Override
@@ -77,6 +86,11 @@ public class DeviceInactiveCondition extends Condition {
mKeyguardStateController.addCallback(mKeyguardStateCallback);
mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateCallback);
mWakefulnessLifecycle.addObserver(mWakefulnessObserver);
+ mAnyDozeListenerJob = mJavaAdapter.alwaysCollectFlow(
+ mKeyguardInteractor.getDozeTransitionModel(), dozeModel -> {
+ mAnyDoze = !DozeStateModel.Companion.isDozeOff(dozeModel.getTo());
+ updateState();
+ });
}
@Override
@@ -84,6 +98,7 @@ public class DeviceInactiveCondition extends Condition {
mKeyguardStateController.removeCallback(mKeyguardStateCallback);
mKeyguardUpdateMonitor.removeCallback(mKeyguardUpdateCallback);
mWakefulnessLifecycle.removeObserver(mWakefulnessObserver);
+ mAnyDozeListenerJob.cancel(null);
}
@Override
@@ -92,10 +107,10 @@ public class DeviceInactiveCondition extends Condition {
}
private void updateState() {
- final boolean asleep =
- mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_ASLEEP
- || mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_GOING_TO_SLEEP;
- updateCondition(asleep || mKeyguardStateController.isShowing()
- || mKeyguardUpdateMonitor.isDreaming());
+ final boolean asleep = mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_ASLEEP;
+ // Doze/AoD is also a dream, but we should never override it with low light as to the user
+ // it's totally unrelated.
+ updateCondition(!mAnyDoze && (asleep || mKeyguardStateController.isShowing()
+ || mKeyguardUpdateMonitor.isDreaming()));
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/lowlightclock/dagger/LowLightModule.java b/packages/SystemUI/src/com/android/systemui/lowlightclock/dagger/LowLightModule.java
index 8469cb4ab565..f8072f2f79b4 100644
--- a/packages/SystemUI/src/com/android/systemui/lowlightclock/dagger/LowLightModule.java
+++ b/packages/SystemUI/src/com/android/systemui/lowlightclock/dagger/LowLightModule.java
@@ -78,7 +78,7 @@ public abstract class LowLightModule {
@Provides
@IntoSet
- @Named(com.android.systemui.lowlightclock.dagger.LowLightModule.LOW_LIGHT_PRECONDITIONS)
+ @Named(LOW_LIGHT_PRECONDITIONS)
static Condition provideLowLightCondition(LowLightCondition lowLightCondition,
DirectBootCondition directBootCondition) {
// Start lowlight if we are either in lowlight or in direct boot. The ordering of the