diff options
author | 2025-03-22 13:13:13 -0700 | |
---|---|---|
committer | 2025-03-22 13:13:13 -0700 | |
commit | 68c80f9a909b04f257808b8e8ba9d7e65cb6896b (patch) | |
tree | 0a9abcfcfdf5170254f96eee877c03c7e8c16e54 /packages/SystemUI/src | |
parent | cda8332969831337cb68982e4b66764bee9005e9 (diff) | |
parent | bdb510af8e97a897c1bf97650be73380c5d43749 (diff) |
Merge changes Ie6b4dd45,Id10a59d6 into main
* changes:
Listen to DisplayStateInteractor for LowLightMonitor display changes.
Convert LowLightMonitor to kotlin.
Diffstat (limited to 'packages/SystemUI/src')
5 files changed, 263 insertions, 301 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/lowlightclock/AmbientLightModeMonitor.kt b/packages/SystemUI/src/com/android/systemui/lowlightclock/AmbientLightModeMonitor.kt index c1658e1f1694..5e9e930812a6 100644 --- a/packages/SystemUI/src/com/android/systemui/lowlightclock/AmbientLightModeMonitor.kt +++ b/packages/SystemUI/src/com/android/systemui/lowlightclock/AmbientLightModeMonitor.kt @@ -23,7 +23,7 @@ import android.hardware.SensorEventListener import android.hardware.SensorManager import android.util.Log import com.android.systemui.Dumpable -import com.android.systemui.lowlightclock.dagger.LowLightModule.LIGHT_SENSOR +import com.android.systemui.lowlightclock.dagger.LowLightModule.Companion.LIGHT_SENSOR import com.android.systemui.util.sensors.AsyncSensorManager import java.io.PrintWriter import java.util.Optional diff --git a/packages/SystemUI/src/com/android/systemui/lowlightclock/LowLightMonitor.java b/packages/SystemUI/src/com/android/systemui/lowlightclock/LowLightMonitor.java deleted file mode 100644 index e5eec64ac615..000000000000 --- a/packages/SystemUI/src/com/android/systemui/lowlightclock/LowLightMonitor.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (C) 2024 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.lowlightclock; - -import static com.android.dream.lowlight.LowLightDreamManager.AMBIENT_LIGHT_MODE_LOW_LIGHT; -import static com.android.dream.lowlight.LowLightDreamManager.AMBIENT_LIGHT_MODE_REGULAR; -import static com.android.systemui.dreams.dagger.DreamModule.LOW_LIGHT_DREAM_SERVICE; -import static com.android.systemui.keyguard.ScreenLifecycle.SCREEN_ON; -import static com.android.systemui.lowlightclock.dagger.LowLightModule.LOW_LIGHT_PRECONDITIONS; - -import android.content.ComponentName; -import android.content.pm.PackageManager; - -import androidx.annotation.Nullable; - -import com.android.dream.lowlight.LowLightDreamManager; -import com.android.systemui.dagger.qualifiers.Background; -import com.android.systemui.dagger.qualifiers.SystemUser; -import com.android.systemui.keyguard.ScreenLifecycle; -import com.android.systemui.shared.condition.Condition; -import com.android.systemui.shared.condition.Monitor; -import com.android.systemui.util.condition.ConditionalCoreStartable; - -import dagger.Lazy; - -import java.util.Set; -import java.util.concurrent.Executor; - -import javax.inject.Inject; -import javax.inject.Named; - -/** - * Tracks environment (low-light or not) in order to correctly show or hide a low-light clock while - * dreaming. - */ -public class LowLightMonitor extends ConditionalCoreStartable implements Monitor.Callback, - ScreenLifecycle.Observer { - private static final String TAG = "LowLightMonitor"; - - private final Lazy<LowLightDreamManager> mLowLightDreamManager; - private final Monitor mConditionsMonitor; - private final Lazy<Set<Condition>> mLowLightConditions; - private Monitor.Subscription.Token mSubscriptionToken; - private ScreenLifecycle mScreenLifecycle; - private final LowLightLogger mLogger; - - private final ComponentName mLowLightDreamService; - - private final PackageManager mPackageManager; - - private final Executor mExecutor; - - @Inject - public LowLightMonitor(Lazy<LowLightDreamManager> lowLightDreamManager, - @SystemUser Monitor conditionsMonitor, - @Named(LOW_LIGHT_PRECONDITIONS) Lazy<Set<Condition>> lowLightConditions, - ScreenLifecycle screenLifecycle, - LowLightLogger lowLightLogger, - @Nullable @Named(LOW_LIGHT_DREAM_SERVICE) ComponentName lowLightDreamService, - PackageManager packageManager, - @Background Executor backgroundExecutor) { - super(conditionsMonitor); - mLowLightDreamManager = lowLightDreamManager; - mConditionsMonitor = conditionsMonitor; - mLowLightConditions = lowLightConditions; - mScreenLifecycle = screenLifecycle; - mLogger = lowLightLogger; - mLowLightDreamService = lowLightDreamService; - mPackageManager = packageManager; - mExecutor = backgroundExecutor; - } - - @Override - public void onConditionsChanged(boolean allConditionsMet) { - mExecutor.execute(() -> { - mLogger.d(TAG, "Low light enabled: " + allConditionsMet); - - mLowLightDreamManager.get().setAmbientLightMode(allConditionsMet - ? AMBIENT_LIGHT_MODE_LOW_LIGHT : AMBIENT_LIGHT_MODE_REGULAR); - }); - } - - @Override - public void onScreenTurnedOn() { - mExecutor.execute(() -> { - if (mSubscriptionToken == null) { - mLogger.d(TAG, "Screen turned on. Subscribing to low light conditions."); - - mSubscriptionToken = mConditionsMonitor.addSubscription( - new Monitor.Subscription.Builder(this) - .addConditions(mLowLightConditions.get()) - .build()); - } - }); - } - - - @Override - public void onScreenTurnedOff() { - mExecutor.execute(() -> { - if (mSubscriptionToken != null) { - mLogger.d(TAG, "Screen turned off. Removing subscription to low light conditions."); - - mConditionsMonitor.removeSubscription(mSubscriptionToken); - mSubscriptionToken = null; - } - }); - } - - @Override - protected void onStart() { - mExecutor.execute(() -> { - if (mLowLightDreamService != null) { - // Note that the dream service is disabled by default. This prevents the dream from - // appearing in settings on devices that don't have it explicitly excluded (done in - // the settings overlay). Therefore, the component is enabled if it is to be used - // here. - mPackageManager.setComponentEnabledSetting( - mLowLightDreamService, - PackageManager.COMPONENT_ENABLED_STATE_ENABLED, - PackageManager.DONT_KILL_APP - ); - } else { - // If there is no low light dream service, do not observe conditions. - return; - } - - mScreenLifecycle.addObserver(this); - if (mScreenLifecycle.getScreenState() == SCREEN_ON) { - onScreenTurnedOn(); - } - }); - - } -} diff --git a/packages/SystemUI/src/com/android/systemui/lowlightclock/LowLightMonitor.kt b/packages/SystemUI/src/com/android/systemui/lowlightclock/LowLightMonitor.kt new file mode 100644 index 000000000000..137226332e38 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/lowlightclock/LowLightMonitor.kt @@ -0,0 +1,116 @@ +/* + * 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.lowlightclock + +import android.content.ComponentName +import android.content.pm.PackageManager +import com.android.dream.lowlight.LowLightDreamManager +import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractor +import com.android.systemui.dagger.qualifiers.Background +import com.android.systemui.dagger.qualifiers.SystemUser +import com.android.systemui.dreams.dagger.DreamModule +import com.android.systemui.lowlightclock.dagger.LowLightModule +import com.android.systemui.shared.condition.Condition +import com.android.systemui.shared.condition.Monitor +import com.android.systemui.util.condition.ConditionalCoreStartable +import com.android.systemui.util.kotlin.BooleanFlowOperators.not +import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow +import dagger.Lazy +import javax.inject.Inject +import javax.inject.Named +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.channels.awaitClose +import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.launch + +/** + * Tracks environment (low-light or not) in order to correctly show or hide a low-light clock while + * dreaming. + */ +class LowLightMonitor +@Inject +constructor( + private val lowLightDreamManager: Lazy<LowLightDreamManager>, + @param:SystemUser private val conditionsMonitor: Monitor, + @param:Named(LowLightModule.LOW_LIGHT_PRECONDITIONS) + private val lowLightConditions: Lazy<Set<Condition>>, + displayStateInteractor: DisplayStateInteractor, + private val logger: LowLightLogger, + @param:Named(DreamModule.LOW_LIGHT_DREAM_SERVICE) + private val lowLightDreamService: ComponentName?, + private val packageManager: PackageManager, + @Background private val scope: CoroutineScope, +) : ConditionalCoreStartable(conditionsMonitor) { + private val isScreenOn = not(displayStateInteractor.isDefaultDisplayOff).distinctUntilChanged() + + private val isLowLight = conflatedCallbackFlow { + val token = + conditionsMonitor.addSubscription( + Monitor.Subscription.Builder { trySend(it) } + .addConditions(lowLightConditions.get()) + .build() + ) + + awaitClose { conditionsMonitor.removeSubscription(token) } + } + + @OptIn(ExperimentalCoroutinesApi::class) + override fun onStart() { + scope.launch { + if (lowLightDreamService != null) { + // Note that the dream service is disabled by default. This prevents the dream from + // appearing in settings on devices that don't have it explicitly excluded (done in + // the settings overlay). Therefore, the component is enabled if it is to be used + // here. + packageManager.setComponentEnabledSetting( + lowLightDreamService, + PackageManager.COMPONENT_ENABLED_STATE_ENABLED, + PackageManager.DONT_KILL_APP, + ) + } else { + // If there is no low light dream service, do not observe conditions. + return@launch + } + + isScreenOn + .flatMapLatest { + if (it) { + isLowLight + } else { + flowOf(false) + } + } + .distinctUntilChanged() + .collect { + logger.d(TAG, "Low light enabled: $it") + lowLightDreamManager + .get() + .setAmbientLightMode( + if (it) LowLightDreamManager.AMBIENT_LIGHT_MODE_LOW_LIGHT + else LowLightDreamManager.AMBIENT_LIGHT_MODE_REGULAR + ) + } + } + } + + companion object { + private const val TAG = "LowLightMonitor" + } +} diff --git a/packages/SystemUI/src/com/android/systemui/lowlightclock/dagger/LowLightModule.java b/packages/SystemUI/src/com/android/systemui/lowlightclock/dagger/LowLightModule.java deleted file mode 100644 index f8072f2f79b4..000000000000 --- a/packages/SystemUI/src/com/android/systemui/lowlightclock/dagger/LowLightModule.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (C) 2024 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.lowlightclock.dagger; - -import android.annotation.Nullable; -import android.content.res.Resources; -import android.hardware.Sensor; - -import com.android.dream.lowlight.dagger.LowLightDreamModule; -import com.android.systemui.CoreStartable; -import com.android.systemui.communal.DeviceInactiveCondition; -import com.android.systemui.dagger.SysUISingleton; -import com.android.systemui.dagger.qualifiers.Main; -import com.android.systemui.log.LogBuffer; -import com.android.systemui.log.LogBufferFactory; -import com.android.systemui.lowlightclock.AmbientLightModeMonitor; -import com.android.systemui.lowlightclock.DirectBootCondition; -import com.android.systemui.lowlightclock.ForceLowLightCondition; -import com.android.systemui.lowlightclock.LowLightCondition; -import com.android.systemui.lowlightclock.LowLightDisplayController; -import com.android.systemui.lowlightclock.LowLightMonitor; -import com.android.systemui.lowlightclock.ScreenSaverEnabledCondition; -import com.android.systemui.res.R; -import com.android.systemui.shared.condition.Condition; - -import dagger.Binds; -import dagger.BindsOptionalOf; -import dagger.Module; -import dagger.Provides; -import dagger.multibindings.ClassKey; -import dagger.multibindings.IntoMap; -import dagger.multibindings.IntoSet; - -import javax.inject.Named; - -@Module(includes = LowLightDreamModule.class) -public abstract class LowLightModule { - public static final String Y_TRANSLATION_ANIMATION_OFFSET = - "y_translation_animation_offset"; - public static final String Y_TRANSLATION_ANIMATION_DURATION_MILLIS = - "y_translation_animation_duration_millis"; - public static final String ALPHA_ANIMATION_IN_START_DELAY_MILLIS = - "alpha_animation_in_start_delay_millis"; - public static final String ALPHA_ANIMATION_DURATION_MILLIS = - "alpha_animation_duration_millis"; - public static final String LOW_LIGHT_PRECONDITIONS = "low_light_preconditions"; - public static final String LIGHT_SENSOR = "low_light_monitor_light_sensor"; - - - /** - * Provides a {@link LogBuffer} for logs related to low-light features. - */ - @Provides - @SysUISingleton - @LowLightLog - public static LogBuffer provideLowLightLogBuffer(LogBufferFactory factory) { - return factory.create("LowLightLog", 250); - } - - @Binds - @IntoSet - @Named(LOW_LIGHT_PRECONDITIONS) - abstract Condition bindScreenSaverEnabledCondition(ScreenSaverEnabledCondition condition); - - @Provides - @IntoSet - @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 - // conditions matters here since we don't want to start the lowlight condition if - // we are in direct boot mode. - return directBootCondition.or(lowLightCondition); - } - - @Binds - @IntoSet - @Named(LOW_LIGHT_PRECONDITIONS) - abstract Condition bindForceLowLightCondition(ForceLowLightCondition condition); - - @Binds - @IntoSet - @Named(LOW_LIGHT_PRECONDITIONS) - abstract Condition bindDeviceInactiveCondition(DeviceInactiveCondition condition); - - @BindsOptionalOf - abstract LowLightDisplayController bindsLowLightDisplayController(); - - @BindsOptionalOf - @Nullable - @Named(LIGHT_SENSOR) - abstract Sensor bindsLightSensor(); - - @BindsOptionalOf - abstract AmbientLightModeMonitor.DebounceAlgorithm bindsDebounceAlgorithm(); - - /** - * - */ - @Provides - @Named(Y_TRANSLATION_ANIMATION_OFFSET) - static int providesAnimationInOffset(@Main Resources resources) { - return resources.getDimensionPixelOffset( - R.dimen.low_light_clock_translate_animation_offset); - } - - /** - * - */ - @Provides - @Named(Y_TRANSLATION_ANIMATION_DURATION_MILLIS) - static long providesAnimationDurationMillis(@Main Resources resources) { - return resources.getInteger(R.integer.low_light_clock_translate_animation_duration_ms); - } - - /** - * - */ - @Provides - @Named(ALPHA_ANIMATION_IN_START_DELAY_MILLIS) - static long providesAlphaAnimationInStartDelayMillis(@Main Resources resources) { - return resources.getInteger(R.integer.low_light_clock_alpha_animation_in_start_delay_ms); - } - - /** - * - */ - @Provides - @Named(ALPHA_ANIMATION_DURATION_MILLIS) - static long providesAlphaAnimationDurationMillis(@Main Resources resources) { - return resources.getInteger(R.integer.low_light_clock_alpha_animation_duration_ms); - } - /** Inject into LowLightMonitor. */ - @Binds - @IntoMap - @ClassKey(LowLightMonitor.class) - abstract CoreStartable bindLowLightMonitor(LowLightMonitor lowLightMonitor); -} diff --git a/packages/SystemUI/src/com/android/systemui/lowlightclock/dagger/LowLightModule.kt b/packages/SystemUI/src/com/android/systemui/lowlightclock/dagger/LowLightModule.kt new file mode 100644 index 000000000000..6b3254e928ec --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/lowlightclock/dagger/LowLightModule.kt @@ -0,0 +1,146 @@ +/* + * 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.lowlightclock.dagger + +import android.content.res.Resources +import android.hardware.Sensor +import com.android.dream.lowlight.dagger.LowLightDreamModule +import com.android.systemui.CoreStartable +import com.android.systemui.communal.DeviceInactiveCondition +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.dagger.qualifiers.Main +import com.android.systemui.log.LogBuffer +import com.android.systemui.log.LogBufferFactory +import com.android.systemui.lowlightclock.AmbientLightModeMonitor.DebounceAlgorithm +import com.android.systemui.lowlightclock.DirectBootCondition +import com.android.systemui.lowlightclock.ForceLowLightCondition +import com.android.systemui.lowlightclock.LowLightCondition +import com.android.systemui.lowlightclock.LowLightDisplayController +import com.android.systemui.lowlightclock.LowLightMonitor +import com.android.systemui.lowlightclock.ScreenSaverEnabledCondition +import com.android.systemui.res.R +import com.android.systemui.shared.condition.Condition +import dagger.Binds +import dagger.BindsOptionalOf +import dagger.Module +import dagger.Provides +import dagger.multibindings.ClassKey +import dagger.multibindings.IntoMap +import dagger.multibindings.IntoSet +import javax.inject.Named + +@Module(includes = [LowLightDreamModule::class]) +abstract class LowLightModule { + @Binds + @IntoSet + @Named(LOW_LIGHT_PRECONDITIONS) + abstract fun bindScreenSaverEnabledCondition(condition: ScreenSaverEnabledCondition): Condition + + @Binds + @IntoSet + @Named(LOW_LIGHT_PRECONDITIONS) + abstract fun bindForceLowLightCondition(condition: ForceLowLightCondition): Condition + + @Binds + @IntoSet + @Named(LOW_LIGHT_PRECONDITIONS) + abstract fun bindDeviceInactiveCondition(condition: DeviceInactiveCondition): Condition + + @BindsOptionalOf abstract fun bindsLowLightDisplayController(): LowLightDisplayController + + @BindsOptionalOf @Named(LIGHT_SENSOR) abstract fun bindsLightSensor(): Sensor + + @BindsOptionalOf abstract fun bindsDebounceAlgorithm(): DebounceAlgorithm + + /** Inject into LowLightMonitor. */ + @Binds + @IntoMap + @ClassKey(LowLightMonitor::class) + abstract fun bindLowLightMonitor(lowLightMonitor: LowLightMonitor): CoreStartable + + companion object { + const val Y_TRANSLATION_ANIMATION_OFFSET: String = "y_translation_animation_offset" + const val Y_TRANSLATION_ANIMATION_DURATION_MILLIS: String = + "y_translation_animation_duration_millis" + const val ALPHA_ANIMATION_IN_START_DELAY_MILLIS: String = + "alpha_animation_in_start_delay_millis" + const val ALPHA_ANIMATION_DURATION_MILLIS: String = "alpha_animation_duration_millis" + const val LOW_LIGHT_PRECONDITIONS: String = "low_light_preconditions" + const val LIGHT_SENSOR: String = "low_light_monitor_light_sensor" + + /** Provides a [LogBuffer] for logs related to low-light features. */ + @JvmStatic + @Provides + @SysUISingleton + @LowLightLog + fun provideLowLightLogBuffer(factory: LogBufferFactory): LogBuffer { + return factory.create("LowLightLog", 250) + } + + @Provides + @IntoSet + @Named(LOW_LIGHT_PRECONDITIONS) + fun provideLowLightCondition( + lowLightCondition: LowLightCondition, + directBootCondition: DirectBootCondition, + ): Condition { + // Start lowlight if we are either in lowlight or in direct boot. The ordering of the + // conditions matters here since we don't want to start the lowlight condition if + // we are in direct boot mode. + return directBootCondition.or(lowLightCondition) + } + + /** */ + @JvmStatic + @Provides + @Named(Y_TRANSLATION_ANIMATION_OFFSET) + fun providesAnimationInOffset(@Main resources: Resources): Int { + return resources.getDimensionPixelOffset( + R.dimen.low_light_clock_translate_animation_offset + ) + } + + /** */ + @JvmStatic + @Provides + @Named(Y_TRANSLATION_ANIMATION_DURATION_MILLIS) + fun providesAnimationDurationMillis(@Main resources: Resources): Long { + return resources + .getInteger(R.integer.low_light_clock_translate_animation_duration_ms) + .toLong() + } + + /** */ + @JvmStatic + @Provides + @Named(ALPHA_ANIMATION_IN_START_DELAY_MILLIS) + fun providesAlphaAnimationInStartDelayMillis(@Main resources: Resources): Long { + return resources + .getInteger(R.integer.low_light_clock_alpha_animation_in_start_delay_ms) + .toLong() + } + + /** */ + @JvmStatic + @Provides + @Named(ALPHA_ANIMATION_DURATION_MILLIS) + fun providesAlphaAnimationDurationMillis(@Main resources: Resources): Long { + return resources + .getInteger(R.integer.low_light_clock_alpha_animation_duration_ms) + .toLong() + } + } +} |