Loading packages/SystemUI/src/com/android/keyguard/ClockEventController.kt +175 −155 Original line number Diff line number Diff line Loading @@ -24,8 +24,8 @@ import android.content.res.Resources import android.text.format.DateFormat import android.util.TypedValue import android.view.View import android.widget.FrameLayout import android.view.ViewTreeObserver import android.widget.FrameLayout import androidx.annotation.VisibleForTesting import androidx.lifecycle.Lifecycle import androidx.lifecycle.repeatOnLifecycle Loading @@ -40,8 +40,8 @@ import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor import com.android.systemui.keyguard.shared.model.TransitionState import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.log.dagger.KeyguardSmallClockLog import com.android.systemui.log.dagger.KeyguardLargeClockLog import com.android.systemui.log.dagger.KeyguardSmallClockLog import com.android.systemui.plugins.ClockController import com.android.systemui.plugins.ClockFaceController import com.android.systemui.plugins.ClockTickRate Loading @@ -53,22 +53,24 @@ import com.android.systemui.statusbar.policy.BatteryController import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.util.concurrency.DelayableExecutor import java.util.Locale import java.util.TimeZone import java.util.concurrent.Executor import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.DisposableHandle import kotlinx.coroutines.Job import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.filter import kotlinx.coroutines.launch import java.util.Locale import java.util.TimeZone import java.util.concurrent.Executor import javax.inject.Inject /** * Controller for a Clock provided by the registry and used on the keyguard. Instantiated by * [KeyguardClockSwitchController]. Functionality is forked from [AnimatableClockController]. */ open class ClockEventController @Inject constructor( open class ClockEventController @Inject constructor( private val keyguardInteractor: KeyguardInteractor, private val keyguardTransitionInteractor: KeyguardTransitionInteractor, private val broadcastDispatcher: BroadcastDispatcher, Loading Loading @@ -115,7 +117,8 @@ open class ClockEventController @Inject constructor( private var disposableHandle: DisposableHandle? = null private val regionSamplingEnabled = featureFlags.isEnabled(REGION_SAMPLING) private val mLayoutChangedListener = object : View.OnLayoutChangeListener { private val mLayoutChangedListener = object : View.OnLayoutChangeListener { private var currentSmallClockView: View? = null private var currentLargeClockView: View? = null private var currentSmallClockLocation = IntArray(2) Loading @@ -141,10 +144,14 @@ open class ClockEventController @Inject constructor( // SMALL CLOCK if (parent.id == R.id.lockscreen_clock_view) { // view bounds have changed due to clock size changing (i.e. different character widths) // AND/OR the view has been translated when transitioning between small and large clock if (view != currentSmallClockView || !view.locationOnScreen.contentEquals(currentSmallClockLocation)) { // view bounds have changed due to clock size changing (i.e. different character // widths) // AND/OR the view has been translated when transitioning between small and // large clock if ( view != currentSmallClockView || !view.locationOnScreen.contentEquals(currentSmallClockLocation) ) { currentSmallClockView = view currentSmallClockLocation = view.locationOnScreen updateRegionSampler(view) Loading @@ -152,8 +159,10 @@ open class ClockEventController @Inject constructor( } // LARGE CLOCK else if (parent.id == R.id.lockscreen_clock_view_large) { if (view != currentLargeClockView || !view.locationOnScreen.contentEquals(currentLargeClockLocation)) { if ( view != currentLargeClockView || !view.locationOnScreen.contentEquals(currentLargeClockLocation) ) { currentLargeClockView = view currentLargeClockLocation = view.locationOnScreen updateRegionSampler(view) Loading Loading @@ -189,13 +198,15 @@ open class ClockEventController @Inject constructor( private fun updateRegionSampler(sampledRegion: View) { regionSampler?.stopRegionSampler() regionSampler = createRegionSampler( regionSampler = createRegionSampler( sampledRegion, mainExecutor, bgExecutor, regionSamplingEnabled, ::updateColors )?.apply { startRegionSampler() } ) ?.apply { startRegionSampler() } updateColors() } Loading @@ -212,7 +223,8 @@ open class ClockEventController @Inject constructor( mainExecutor, bgExecutor, regionSamplingEnabled, updateColors) updateColors ) } var regionSampler: RegionSampler? = null Loading @@ -224,7 +236,8 @@ open class ClockEventController @Inject constructor( private var smallClockIsDark = true private var largeClockIsDark = true private val configListener = object : ConfigurationController.ConfigurationListener { private val configListener = object : ConfigurationController.ConfigurationListener { override fun onThemeChanged() { clock?.events?.onColorPaletteChanged(resources) updateColors() Loading @@ -235,7 +248,8 @@ open class ClockEventController @Inject constructor( } } private val batteryCallback = object : BatteryStateChangeCallback { private val batteryCallback = object : BatteryStateChangeCallback { override fun onBatteryLevelChanged(level: Int, pluggedIn: Boolean, charging: Boolean) { if (isKeyguardVisible && !isCharging && charging) { clock?.animations?.charge() Loading @@ -244,13 +258,15 @@ open class ClockEventController @Inject constructor( } } private val localeBroadcastReceiver = object : BroadcastReceiver() { private val localeBroadcastReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { clock?.events?.onLocaleChanged(Locale.getDefault()) } } private val keyguardUpdateMonitorCallback = object : KeyguardUpdateMonitorCallback() { private val keyguardUpdateMonitorCallback = object : KeyguardUpdateMonitorCallback() { override fun onKeyguardVisibilityChanged(visible: Boolean) { isKeyguardVisible = visible if (!featureFlags.isEnabled(DOZING_MIGRATION_1)) { Loading Loading @@ -295,7 +311,8 @@ open class ClockEventController @Inject constructor( configurationController.addCallback(configListener) batteryController.addCallback(batteryCallback) keyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback) disposableHandle = parent.repeatWhenAttached { disposableHandle = parent.repeatWhenAttached { repeatOnLifecycle(Lifecycle.State.STARTED) { listenForDozing(this) if (featureFlags.isEnabled(DOZING_MIGRATION_1)) { Loading Loading @@ -344,10 +361,18 @@ open class ClockEventController @Inject constructor( } private fun updateFontSizes() { clock?.smallClock?.events?.onFontSettingChanged( resources.getDimensionPixelSize(R.dimen.small_clock_text_size).toFloat()) clock?.largeClock?.events?.onFontSettingChanged( resources.getDimensionPixelSize(R.dimen.large_clock_text_size).toFloat()) clock ?.smallClock ?.events ?.onFontSettingChanged( resources.getDimensionPixelSize(R.dimen.small_clock_text_size).toFloat() ) clock ?.largeClock ?.events ?.onFontSettingChanged( resources.getDimensionPixelSize(R.dimen.large_clock_text_size).toFloat() ) } private fun handleDoze(doze: Float) { Loading @@ -359,34 +384,25 @@ open class ClockEventController @Inject constructor( @VisibleForTesting internal fun listenForDozeAmount(scope: CoroutineScope): Job { return scope.launch { keyguardInteractor.dozeAmount.collect { handleDoze(it) } } return scope.launch { keyguardInteractor.dozeAmount.collect { handleDoze(it) } } } @VisibleForTesting internal fun listenForDozeAmountTransition(scope: CoroutineScope): Job { return scope.launch { keyguardTransitionInteractor.dozeAmountTransition.collect { handleDoze(it.value) } keyguardTransitionInteractor.dozeAmountTransition.collect { handleDoze(it.value) } } } /** * When keyguard is displayed again after being gone, the clock must be reset to full * dozing. * When keyguard is displayed again after being gone, the clock must be reset to full dozing. */ @VisibleForTesting internal fun listenForAnyStateToAodTransition(scope: CoroutineScope): Job { return scope.launch { keyguardTransitionInteractor.anyStateToAodTransition.filter { it.transitionState == TransitionState.FINISHED }.collect { handleDoze(1f) } keyguardTransitionInteractor.anyStateToAodTransition .filter { it.transitionState == TransitionState.FINISHED } .collect { handleDoze(1f) } } } Loading @@ -399,19 +415,19 @@ open class ClockEventController @Inject constructor( ) { localDozeAmount, localIsDozing -> localDozeAmount > dozeAmount || localIsDozing } .collect { localIsDozing -> isDozing = localIsDozing } .collect { localIsDozing -> isDozing = localIsDozing } } } class TimeListener(val clockFace: ClockFaceController, val executor: DelayableExecutor) { val predrawListener = ViewTreeObserver.OnPreDrawListener { val predrawListener = ViewTreeObserver.OnPreDrawListener { clockFace.events.onTimeTick() true } val secondsRunnable = object : Runnable { val secondsRunnable = object : Runnable { override fun run() { if (!isRunning) { return Loading @@ -432,7 +448,9 @@ open class ClockEventController @Inject constructor( isRunning = true when (clockFace.events.tickRate) { ClockTickRate.PER_MINUTE -> {/* Handled by KeyguardClockSwitchController */} ClockTickRate.PER_MINUTE -> { /* Handled by KeyguardClockSwitchController */ } ClockTickRate.PER_SECOND -> executor.execute(secondsRunnable) ClockTickRate.PER_FRAME -> { clockFace.view.viewTreeObserver.addOnPreDrawListener(predrawListener) Loading @@ -442,7 +460,9 @@ open class ClockEventController @Inject constructor( } fun stop() { if (!isRunning) { return } if (!isRunning) { return } isRunning = false clockFace.view.viewTreeObserver.removeOnPreDrawListener(predrawListener) Loading packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt +28 −1 Original line number Diff line number Diff line Loading @@ -22,6 +22,8 @@ import android.graphics.Point import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow import com.android.systemui.dagger.SysUISingleton import com.android.systemui.flags.FeatureFlags import com.android.systemui.flags.Flags import com.android.systemui.keyguard.data.repository.KeyguardRepository import com.android.systemui.keyguard.shared.model.BiometricUnlockModel import com.android.systemui.keyguard.shared.model.CameraLaunchSourceModel Loading @@ -31,7 +33,6 @@ import com.android.systemui.keyguard.shared.model.DozeTransitionModel import com.android.systemui.keyguard.shared.model.StatusBarState import com.android.systemui.keyguard.shared.model.WakefulnessModel import com.android.systemui.statusbar.CommandQueue import com.android.systemui.statusbar.CommandQueue.Callbacks import javax.inject.Inject import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.delay Loading @@ -41,7 +42,9 @@ import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.merge import kotlinx.coroutines.flow.onStart /** * Encapsulates business-logic related to the keyguard but not to a more specific part within it. Loading @@ -52,6 +55,7 @@ class KeyguardInteractor constructor( private val repository: KeyguardRepository, private val commandQueue: CommandQueue, featureFlags: FeatureFlags, ) { /** * The amount of doze the system is in, where `1.0` is fully dozing and `0.0` is not dozing at Loading Loading @@ -129,6 +133,29 @@ constructor( */ val biometricUnlockState: Flow<BiometricUnlockModel> = repository.biometricUnlockState /** Keyguard is present and is not occluded. */ val isKeyguardVisible: Flow<Boolean> = combine(isKeyguardShowing, isKeyguardOccluded) { showing, occluded -> showing && !occluded } /** Whether camera is launched over keyguard. */ var isSecureCameraActive = if (featureFlags.isEnabled(Flags.FACE_AUTH_REFACTOR)) { combine( isKeyguardVisible, repository.isBouncerShowing, onCameraLaunchDetected, ) { isKeyguardVisible, isBouncerShowing, cameraLaunchEvent -> when { isKeyguardVisible -> false isBouncerShowing -> false else -> cameraLaunchEvent == CameraLaunchSourceModel.POWER_DOUBLE_TAP } } .onStart { emit(false) } } else { flowOf(false) } /** The approximate location on the screen of the fingerprint sensor, if one is available. */ val fingerprintSensorLocation: Flow<Point?> = repository.fingerprintSensorLocation Loading packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt +4 −2 Original line number Diff line number Diff line Loading @@ -58,7 +58,7 @@ import org.mockito.Mockito.never import org.mockito.Mockito.times import org.mockito.Mockito.verify import org.mockito.junit.MockitoJUnit import java.util.* import java.util.TimeZone import java.util.concurrent.Executor import org.mockito.Mockito.`when` as whenever Loading Loading @@ -105,7 +105,9 @@ class ClockEventControllerTest : SysuiTestCase() { repository = FakeKeyguardRepository() underTest = ClockEventController( KeyguardInteractor(repository = repository, commandQueue = commandQueue), KeyguardInteractor(repository = repository, commandQueue = commandQueue, featureFlags = featureFlags), KeyguardTransitionInteractor(repository = transitionRepository), broadcastDispatcher, batteryController, Loading packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerBaseTest.java +3 −1 Original line number Diff line number Diff line Loading @@ -159,7 +159,9 @@ public class LockIconViewControllerBaseTest extends SysuiTestCase { mAuthRippleController, mResources, new KeyguardTransitionInteractor(mTransitionRepository), new KeyguardInteractor(new FakeKeyguardRepository(), mCommandQueue), new KeyguardInteractor(new FakeKeyguardRepository(), mCommandQueue, mFeatureFlags), mFeatureFlags ); } Loading packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt +10 −7 Original line number Diff line number Diff line Loading @@ -157,25 +157,28 @@ class CustomizationProviderTest : SysuiTestCase() { dumpManager = mock(), userHandle = UserHandle.SYSTEM, ) val featureFlags = FakeFeatureFlags().apply { set(Flags.CUSTOMIZABLE_LOCK_SCREEN_QUICK_AFFORDANCES, true) set(Flags.LOCKSCREEN_CUSTOM_CLOCKS, true) set(Flags.REVAMPED_WALLPAPER_UI, true) set(Flags.WALLPAPER_FULLSCREEN_PREVIEW, true) set(Flags.FACE_AUTH_REFACTOR, true) } underTest.interactor = KeyguardQuickAffordanceInteractor( keyguardInteractor = KeyguardInteractor( repository = FakeKeyguardRepository(), commandQueue = commandQueue, featureFlags = featureFlags, ), registry = mock(), lockPatternUtils = lockPatternUtils, keyguardStateController = keyguardStateController, userTracker = userTracker, activityStarter = activityStarter, featureFlags = FakeFeatureFlags().apply { set(Flags.CUSTOMIZABLE_LOCK_SCREEN_QUICK_AFFORDANCES, true) set(Flags.LOCKSCREEN_CUSTOM_CLOCKS, true) set(Flags.REVAMPED_WALLPAPER_UI, true) set(Flags.WALLPAPER_FULLSCREEN_PREVIEW, true) }, featureFlags = featureFlags, repository = { quickAffordanceRepository }, launchAnimator = launchAnimator, ) Loading Loading
packages/SystemUI/src/com/android/keyguard/ClockEventController.kt +175 −155 Original line number Diff line number Diff line Loading @@ -24,8 +24,8 @@ import android.content.res.Resources import android.text.format.DateFormat import android.util.TypedValue import android.view.View import android.widget.FrameLayout import android.view.ViewTreeObserver import android.widget.FrameLayout import androidx.annotation.VisibleForTesting import androidx.lifecycle.Lifecycle import androidx.lifecycle.repeatOnLifecycle Loading @@ -40,8 +40,8 @@ import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor import com.android.systemui.keyguard.shared.model.TransitionState import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.log.dagger.KeyguardSmallClockLog import com.android.systemui.log.dagger.KeyguardLargeClockLog import com.android.systemui.log.dagger.KeyguardSmallClockLog import com.android.systemui.plugins.ClockController import com.android.systemui.plugins.ClockFaceController import com.android.systemui.plugins.ClockTickRate Loading @@ -53,22 +53,24 @@ import com.android.systemui.statusbar.policy.BatteryController import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.util.concurrency.DelayableExecutor import java.util.Locale import java.util.TimeZone import java.util.concurrent.Executor import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.DisposableHandle import kotlinx.coroutines.Job import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.filter import kotlinx.coroutines.launch import java.util.Locale import java.util.TimeZone import java.util.concurrent.Executor import javax.inject.Inject /** * Controller for a Clock provided by the registry and used on the keyguard. Instantiated by * [KeyguardClockSwitchController]. Functionality is forked from [AnimatableClockController]. */ open class ClockEventController @Inject constructor( open class ClockEventController @Inject constructor( private val keyguardInteractor: KeyguardInteractor, private val keyguardTransitionInteractor: KeyguardTransitionInteractor, private val broadcastDispatcher: BroadcastDispatcher, Loading Loading @@ -115,7 +117,8 @@ open class ClockEventController @Inject constructor( private var disposableHandle: DisposableHandle? = null private val regionSamplingEnabled = featureFlags.isEnabled(REGION_SAMPLING) private val mLayoutChangedListener = object : View.OnLayoutChangeListener { private val mLayoutChangedListener = object : View.OnLayoutChangeListener { private var currentSmallClockView: View? = null private var currentLargeClockView: View? = null private var currentSmallClockLocation = IntArray(2) Loading @@ -141,10 +144,14 @@ open class ClockEventController @Inject constructor( // SMALL CLOCK if (parent.id == R.id.lockscreen_clock_view) { // view bounds have changed due to clock size changing (i.e. different character widths) // AND/OR the view has been translated when transitioning between small and large clock if (view != currentSmallClockView || !view.locationOnScreen.contentEquals(currentSmallClockLocation)) { // view bounds have changed due to clock size changing (i.e. different character // widths) // AND/OR the view has been translated when transitioning between small and // large clock if ( view != currentSmallClockView || !view.locationOnScreen.contentEquals(currentSmallClockLocation) ) { currentSmallClockView = view currentSmallClockLocation = view.locationOnScreen updateRegionSampler(view) Loading @@ -152,8 +159,10 @@ open class ClockEventController @Inject constructor( } // LARGE CLOCK else if (parent.id == R.id.lockscreen_clock_view_large) { if (view != currentLargeClockView || !view.locationOnScreen.contentEquals(currentLargeClockLocation)) { if ( view != currentLargeClockView || !view.locationOnScreen.contentEquals(currentLargeClockLocation) ) { currentLargeClockView = view currentLargeClockLocation = view.locationOnScreen updateRegionSampler(view) Loading Loading @@ -189,13 +198,15 @@ open class ClockEventController @Inject constructor( private fun updateRegionSampler(sampledRegion: View) { regionSampler?.stopRegionSampler() regionSampler = createRegionSampler( regionSampler = createRegionSampler( sampledRegion, mainExecutor, bgExecutor, regionSamplingEnabled, ::updateColors )?.apply { startRegionSampler() } ) ?.apply { startRegionSampler() } updateColors() } Loading @@ -212,7 +223,8 @@ open class ClockEventController @Inject constructor( mainExecutor, bgExecutor, regionSamplingEnabled, updateColors) updateColors ) } var regionSampler: RegionSampler? = null Loading @@ -224,7 +236,8 @@ open class ClockEventController @Inject constructor( private var smallClockIsDark = true private var largeClockIsDark = true private val configListener = object : ConfigurationController.ConfigurationListener { private val configListener = object : ConfigurationController.ConfigurationListener { override fun onThemeChanged() { clock?.events?.onColorPaletteChanged(resources) updateColors() Loading @@ -235,7 +248,8 @@ open class ClockEventController @Inject constructor( } } private val batteryCallback = object : BatteryStateChangeCallback { private val batteryCallback = object : BatteryStateChangeCallback { override fun onBatteryLevelChanged(level: Int, pluggedIn: Boolean, charging: Boolean) { if (isKeyguardVisible && !isCharging && charging) { clock?.animations?.charge() Loading @@ -244,13 +258,15 @@ open class ClockEventController @Inject constructor( } } private val localeBroadcastReceiver = object : BroadcastReceiver() { private val localeBroadcastReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { clock?.events?.onLocaleChanged(Locale.getDefault()) } } private val keyguardUpdateMonitorCallback = object : KeyguardUpdateMonitorCallback() { private val keyguardUpdateMonitorCallback = object : KeyguardUpdateMonitorCallback() { override fun onKeyguardVisibilityChanged(visible: Boolean) { isKeyguardVisible = visible if (!featureFlags.isEnabled(DOZING_MIGRATION_1)) { Loading Loading @@ -295,7 +311,8 @@ open class ClockEventController @Inject constructor( configurationController.addCallback(configListener) batteryController.addCallback(batteryCallback) keyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback) disposableHandle = parent.repeatWhenAttached { disposableHandle = parent.repeatWhenAttached { repeatOnLifecycle(Lifecycle.State.STARTED) { listenForDozing(this) if (featureFlags.isEnabled(DOZING_MIGRATION_1)) { Loading Loading @@ -344,10 +361,18 @@ open class ClockEventController @Inject constructor( } private fun updateFontSizes() { clock?.smallClock?.events?.onFontSettingChanged( resources.getDimensionPixelSize(R.dimen.small_clock_text_size).toFloat()) clock?.largeClock?.events?.onFontSettingChanged( resources.getDimensionPixelSize(R.dimen.large_clock_text_size).toFloat()) clock ?.smallClock ?.events ?.onFontSettingChanged( resources.getDimensionPixelSize(R.dimen.small_clock_text_size).toFloat() ) clock ?.largeClock ?.events ?.onFontSettingChanged( resources.getDimensionPixelSize(R.dimen.large_clock_text_size).toFloat() ) } private fun handleDoze(doze: Float) { Loading @@ -359,34 +384,25 @@ open class ClockEventController @Inject constructor( @VisibleForTesting internal fun listenForDozeAmount(scope: CoroutineScope): Job { return scope.launch { keyguardInteractor.dozeAmount.collect { handleDoze(it) } } return scope.launch { keyguardInteractor.dozeAmount.collect { handleDoze(it) } } } @VisibleForTesting internal fun listenForDozeAmountTransition(scope: CoroutineScope): Job { return scope.launch { keyguardTransitionInteractor.dozeAmountTransition.collect { handleDoze(it.value) } keyguardTransitionInteractor.dozeAmountTransition.collect { handleDoze(it.value) } } } /** * When keyguard is displayed again after being gone, the clock must be reset to full * dozing. * When keyguard is displayed again after being gone, the clock must be reset to full dozing. */ @VisibleForTesting internal fun listenForAnyStateToAodTransition(scope: CoroutineScope): Job { return scope.launch { keyguardTransitionInteractor.anyStateToAodTransition.filter { it.transitionState == TransitionState.FINISHED }.collect { handleDoze(1f) } keyguardTransitionInteractor.anyStateToAodTransition .filter { it.transitionState == TransitionState.FINISHED } .collect { handleDoze(1f) } } } Loading @@ -399,19 +415,19 @@ open class ClockEventController @Inject constructor( ) { localDozeAmount, localIsDozing -> localDozeAmount > dozeAmount || localIsDozing } .collect { localIsDozing -> isDozing = localIsDozing } .collect { localIsDozing -> isDozing = localIsDozing } } } class TimeListener(val clockFace: ClockFaceController, val executor: DelayableExecutor) { val predrawListener = ViewTreeObserver.OnPreDrawListener { val predrawListener = ViewTreeObserver.OnPreDrawListener { clockFace.events.onTimeTick() true } val secondsRunnable = object : Runnable { val secondsRunnable = object : Runnable { override fun run() { if (!isRunning) { return Loading @@ -432,7 +448,9 @@ open class ClockEventController @Inject constructor( isRunning = true when (clockFace.events.tickRate) { ClockTickRate.PER_MINUTE -> {/* Handled by KeyguardClockSwitchController */} ClockTickRate.PER_MINUTE -> { /* Handled by KeyguardClockSwitchController */ } ClockTickRate.PER_SECOND -> executor.execute(secondsRunnable) ClockTickRate.PER_FRAME -> { clockFace.view.viewTreeObserver.addOnPreDrawListener(predrawListener) Loading @@ -442,7 +460,9 @@ open class ClockEventController @Inject constructor( } fun stop() { if (!isRunning) { return } if (!isRunning) { return } isRunning = false clockFace.view.viewTreeObserver.removeOnPreDrawListener(predrawListener) Loading
packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt +28 −1 Original line number Diff line number Diff line Loading @@ -22,6 +22,8 @@ import android.graphics.Point import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow import com.android.systemui.dagger.SysUISingleton import com.android.systemui.flags.FeatureFlags import com.android.systemui.flags.Flags import com.android.systemui.keyguard.data.repository.KeyguardRepository import com.android.systemui.keyguard.shared.model.BiometricUnlockModel import com.android.systemui.keyguard.shared.model.CameraLaunchSourceModel Loading @@ -31,7 +33,6 @@ import com.android.systemui.keyguard.shared.model.DozeTransitionModel import com.android.systemui.keyguard.shared.model.StatusBarState import com.android.systemui.keyguard.shared.model.WakefulnessModel import com.android.systemui.statusbar.CommandQueue import com.android.systemui.statusbar.CommandQueue.Callbacks import javax.inject.Inject import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.delay Loading @@ -41,7 +42,9 @@ import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.merge import kotlinx.coroutines.flow.onStart /** * Encapsulates business-logic related to the keyguard but not to a more specific part within it. Loading @@ -52,6 +55,7 @@ class KeyguardInteractor constructor( private val repository: KeyguardRepository, private val commandQueue: CommandQueue, featureFlags: FeatureFlags, ) { /** * The amount of doze the system is in, where `1.0` is fully dozing and `0.0` is not dozing at Loading Loading @@ -129,6 +133,29 @@ constructor( */ val biometricUnlockState: Flow<BiometricUnlockModel> = repository.biometricUnlockState /** Keyguard is present and is not occluded. */ val isKeyguardVisible: Flow<Boolean> = combine(isKeyguardShowing, isKeyguardOccluded) { showing, occluded -> showing && !occluded } /** Whether camera is launched over keyguard. */ var isSecureCameraActive = if (featureFlags.isEnabled(Flags.FACE_AUTH_REFACTOR)) { combine( isKeyguardVisible, repository.isBouncerShowing, onCameraLaunchDetected, ) { isKeyguardVisible, isBouncerShowing, cameraLaunchEvent -> when { isKeyguardVisible -> false isBouncerShowing -> false else -> cameraLaunchEvent == CameraLaunchSourceModel.POWER_DOUBLE_TAP } } .onStart { emit(false) } } else { flowOf(false) } /** The approximate location on the screen of the fingerprint sensor, if one is available. */ val fingerprintSensorLocation: Flow<Point?> = repository.fingerprintSensorLocation Loading
packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt +4 −2 Original line number Diff line number Diff line Loading @@ -58,7 +58,7 @@ import org.mockito.Mockito.never import org.mockito.Mockito.times import org.mockito.Mockito.verify import org.mockito.junit.MockitoJUnit import java.util.* import java.util.TimeZone import java.util.concurrent.Executor import org.mockito.Mockito.`when` as whenever Loading Loading @@ -105,7 +105,9 @@ class ClockEventControllerTest : SysuiTestCase() { repository = FakeKeyguardRepository() underTest = ClockEventController( KeyguardInteractor(repository = repository, commandQueue = commandQueue), KeyguardInteractor(repository = repository, commandQueue = commandQueue, featureFlags = featureFlags), KeyguardTransitionInteractor(repository = transitionRepository), broadcastDispatcher, batteryController, Loading
packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerBaseTest.java +3 −1 Original line number Diff line number Diff line Loading @@ -159,7 +159,9 @@ public class LockIconViewControllerBaseTest extends SysuiTestCase { mAuthRippleController, mResources, new KeyguardTransitionInteractor(mTransitionRepository), new KeyguardInteractor(new FakeKeyguardRepository(), mCommandQueue), new KeyguardInteractor(new FakeKeyguardRepository(), mCommandQueue, mFeatureFlags), mFeatureFlags ); } Loading
packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt +10 −7 Original line number Diff line number Diff line Loading @@ -157,25 +157,28 @@ class CustomizationProviderTest : SysuiTestCase() { dumpManager = mock(), userHandle = UserHandle.SYSTEM, ) val featureFlags = FakeFeatureFlags().apply { set(Flags.CUSTOMIZABLE_LOCK_SCREEN_QUICK_AFFORDANCES, true) set(Flags.LOCKSCREEN_CUSTOM_CLOCKS, true) set(Flags.REVAMPED_WALLPAPER_UI, true) set(Flags.WALLPAPER_FULLSCREEN_PREVIEW, true) set(Flags.FACE_AUTH_REFACTOR, true) } underTest.interactor = KeyguardQuickAffordanceInteractor( keyguardInteractor = KeyguardInteractor( repository = FakeKeyguardRepository(), commandQueue = commandQueue, featureFlags = featureFlags, ), registry = mock(), lockPatternUtils = lockPatternUtils, keyguardStateController = keyguardStateController, userTracker = userTracker, activityStarter = activityStarter, featureFlags = FakeFeatureFlags().apply { set(Flags.CUSTOMIZABLE_LOCK_SCREEN_QUICK_AFFORDANCES, true) set(Flags.LOCKSCREEN_CUSTOM_CLOCKS, true) set(Flags.REVAMPED_WALLPAPER_UI, true) set(Flags.WALLPAPER_FULLSCREEN_PREVIEW, true) }, featureFlags = featureFlags, repository = { quickAffordanceRepository }, launchAnimator = launchAnimator, ) Loading