blob: 62cf1a624d9b849881c7a3a84e0d26d6a893227e [file] [log] [blame]
/*
* Copyright (C) 2022 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.keyguard.data.repository
import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
import com.android.systemui.common.data.model.Position
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.policy.KeyguardStateController
import javax.inject.Inject
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
/** Defines interface for classes that encapsulate application state for the keyguard. */
interface KeyguardRepository {
/**
* Observable for whether the bottom area UI should animate the transition out of doze state.
*
* To learn more about doze state, please see [isDozing].
*/
val animateBottomAreaDozingTransitions: StateFlow<Boolean>
/**
* Observable for the current amount of alpha that should be used for rendering the bottom area.
* UI.
*/
val bottomAreaAlpha: StateFlow<Float>
/**
* Observable of the relative offset of the lock-screen clock from its natural position on the
* screen.
*/
val clockPosition: StateFlow<Position>
/**
* Observable for whether the keyguard is showing.
*
* Note: this is also `true` when the lock-screen is occluded with an `Activity` "above" it in
* the z-order (which is not really above the system UI window, but rather - the lock-screen
* becomes invisible to reveal the "occluding activity").
*/
val isKeyguardShowing: Flow<Boolean>
/**
* Observable for whether we are in doze state.
*
* Doze state is the same as "Always on Display" or "AOD". It is the state that the device can
* enter to conserve battery when the device is locked and inactive.
*
* Note that it is possible for the system to be transitioning into doze while this flow still
* returns `false`. In order to account for that, observers should also use the [dozeAmount]
* flow to check if it's greater than `0`
*/
val isDozing: Flow<Boolean>
/**
* Observable for the amount of doze we are currently in.
*
* While in doze state, this amount can change - driving a cycle of animations designed to avoid
* pixel burn-in, etc.
*
* Also note that the value here may be greater than `0` while [isDozing] is still `false`, this
* happens during an animation/transition into doze mode. An observer would be wise to account
* for both flows if needed.
*/
val dozeAmount: Flow<Float>
/** Sets whether the bottom area UI should animate the transition out of doze state. */
fun setAnimateDozingTransitions(animate: Boolean)
/** Sets the current amount of alpha that should be used for rendering the bottom area. */
fun setBottomAreaAlpha(alpha: Float)
/**
* Sets the relative offset of the lock-screen clock from its natural position on the screen.
*/
fun setClockPosition(x: Int, y: Int)
}
/** Encapsulates application state for the keyguard. */
@SysUISingleton
class KeyguardRepositoryImpl
@Inject
constructor(
statusBarStateController: StatusBarStateController,
keyguardStateController: KeyguardStateController,
) : KeyguardRepository {
private val _animateBottomAreaDozingTransitions = MutableStateFlow(false)
override val animateBottomAreaDozingTransitions =
_animateBottomAreaDozingTransitions.asStateFlow()
private val _bottomAreaAlpha = MutableStateFlow(1f)
override val bottomAreaAlpha = _bottomAreaAlpha.asStateFlow()
private val _clockPosition = MutableStateFlow(Position(0, 0))
override val clockPosition = _clockPosition.asStateFlow()
override val isKeyguardShowing: Flow<Boolean> = conflatedCallbackFlow {
val callback =
object : KeyguardStateController.Callback {
override fun onKeyguardShowingChanged() {
trySendWithFailureLogging(
keyguardStateController.isShowing,
TAG,
"updated isKeyguardShowing"
)
}
}
keyguardStateController.addCallback(callback)
// Adding the callback does not send an initial update.
trySendWithFailureLogging(
keyguardStateController.isShowing,
TAG,
"initial isKeyguardShowing"
)
awaitClose { keyguardStateController.removeCallback(callback) }
}
override val isDozing: Flow<Boolean> = conflatedCallbackFlow {
val callback =
object : StatusBarStateController.StateListener {
override fun onDozingChanged(isDozing: Boolean) {
trySendWithFailureLogging(isDozing, TAG, "updated isDozing")
}
}
statusBarStateController.addCallback(callback)
trySendWithFailureLogging(statusBarStateController.isDozing, TAG, "initial isDozing")
awaitClose { statusBarStateController.removeCallback(callback) }
}
override val dozeAmount: Flow<Float> = conflatedCallbackFlow {
val callback =
object : StatusBarStateController.StateListener {
override fun onDozeAmountChanged(linear: Float, eased: Float) {
trySendWithFailureLogging(eased, TAG, "updated dozeAmount")
}
}
statusBarStateController.addCallback(callback)
trySendWithFailureLogging(statusBarStateController.dozeAmount, TAG, "initial dozeAmount")
awaitClose { statusBarStateController.removeCallback(callback) }
}
override fun setAnimateDozingTransitions(animate: Boolean) {
_animateBottomAreaDozingTransitions.value = animate
}
override fun setBottomAreaAlpha(alpha: Float) {
_bottomAreaAlpha.value = alpha
}
override fun setClockPosition(x: Int, y: Int) {
_clockPosition.value = Position(x, y)
}
companion object {
private const val TAG = "KeyguardRepositoryImpl"
}
}