diff options
41 files changed, 324 insertions, 172 deletions
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/BottomAreaSection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/BottomAreaSection.kt index 97d5b41000de..467dbca759c8 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/BottomAreaSection.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/BottomAreaSection.kt @@ -32,6 +32,7 @@ import androidx.core.content.res.ResourcesCompat import com.android.compose.animation.scene.ElementKey import com.android.compose.animation.scene.SceneScope import com.android.systemui.animation.view.LaunchableImageView +import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.keyguard.ui.binder.KeyguardIndicationAreaBinder import com.android.systemui.keyguard.ui.binder.KeyguardQuickAffordanceViewBinder import com.android.systemui.keyguard.ui.view.KeyguardIndicationArea @@ -43,6 +44,7 @@ import com.android.systemui.res.R import com.android.systemui.statusbar.KeyguardIndicationController import com.android.systemui.statusbar.VibratorHelper import javax.inject.Inject +import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.DisposableHandle import kotlinx.coroutines.flow.Flow @@ -54,6 +56,7 @@ constructor( private val vibratorHelper: VibratorHelper, private val indicationController: KeyguardIndicationController, private val indicationAreaViewModel: KeyguardIndicationAreaViewModel, + @Main private val mainImmediateDispatcher: CoroutineDispatcher, ) { /** * Renders a single lockscreen shortcut. @@ -161,6 +164,7 @@ constructor( transitionAlpha, falsingManager, vibratorHelper, + mainImmediateDispatcher, ) { indicationController.showTransientIndication(it) } diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/LockSection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/LockSection.kt index 9f02201f1d81..48684a02bd19 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/LockSection.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/LockSection.kt @@ -34,6 +34,7 @@ import com.android.keyguard.LockIconView import com.android.keyguard.LockIconViewController import com.android.systemui.biometrics.AuthController import com.android.systemui.dagger.qualifiers.Application +import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor import com.android.systemui.flags.FeatureFlagsClassic import com.android.systemui.flags.Flags @@ -50,12 +51,14 @@ import com.android.systemui.shade.NotificationPanelView import com.android.systemui.statusbar.VibratorHelper import dagger.Lazy import javax.inject.Inject +import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope class LockSection @Inject constructor( @Application private val applicationScope: CoroutineScope, + @Main private val mainImmediateDispatcher: CoroutineDispatcher, private val windowManager: WindowManager, private val authController: AuthController, private val featureFlags: FeatureFlagsClassic, @@ -93,6 +96,7 @@ constructor( deviceEntryBackgroundViewModel.get(), falsingManager.get(), vibratorHelper.get(), + mainImmediateDispatcher, ) } } else { diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt index eec74efd4751..6d7a0a96a71b 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt @@ -214,14 +214,16 @@ class KeyguardInteractorTest : SysuiTestCase() { ) repository.setStatusBarState(StatusBarState.KEYGUARD) - shadeRepository.setLegacyShadeExpansion(1f) + // User begins to swipe up + shadeRepository.setLegacyShadeExpansion(0.99f) // When not dismissable, no alpha value (null) should emit repository.setKeyguardDismissible(false) assertThat(dismissAlpha).isNull() repository.setKeyguardDismissible(true) - assertThat(dismissAlpha).isGreaterThan(0.95f) + shadeRepository.setLegacyShadeExpansion(0.98f) + assertThat(dismissAlpha).isGreaterThan(0.5f) } @Test diff --git a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt index 48271dea31d8..8a18efc721d8 100644 --- a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt +++ b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt @@ -31,6 +31,7 @@ import android.view.ViewTreeObserver.OnGlobalLayoutListener import androidx.annotation.VisibleForTesting import androidx.lifecycle.Lifecycle import androidx.lifecycle.repeatOnLifecycle +import com.android.app.tracing.coroutines.launch import com.android.systemui.broadcast.BroadcastDispatcher import com.android.systemui.customization.R import com.android.systemui.dagger.qualifiers.Background @@ -65,6 +66,7 @@ import java.util.Locale import java.util.TimeZone import java.util.concurrent.Executor import javax.inject.Inject +import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.DisposableHandle import kotlinx.coroutines.Job @@ -72,7 +74,6 @@ import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.merge -import kotlinx.coroutines.launch /** * Controller for a Clock provided by the registry and used on the keyguard. Instantiated by @@ -90,6 +91,7 @@ constructor( @DisplaySpecific private val resources: Resources, private val context: Context, @Main private val mainExecutor: DelayableExecutor, + @Main private val mainImmediateDispatcher: CoroutineDispatcher, @Background private val bgExecutor: Executor, private val clockBuffers: ClockMessageBuffers, private val featureFlags: FeatureFlagsClassic, @@ -424,7 +426,7 @@ constructor( keyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback) zenModeController.addCallback(zenModeCallback) disposableHandle = - parent.repeatWhenAttached { + parent.repeatWhenAttached(mainImmediateDispatcher) { repeatOnLifecycle(Lifecycle.State.CREATED) { listenForDozing(this) if (MigrateClocksToBlueprint.isEnabled) { @@ -529,12 +531,14 @@ constructor( @VisibleForTesting internal fun listenForDozeAmount(scope: CoroutineScope): Job { - return scope.launch { keyguardInteractor.dozeAmount.collect { handleDoze(it) } } + return scope.launch("$TAG#listenForDozeAmount") { + keyguardInteractor.dozeAmount.collect { handleDoze(it) } + } } @VisibleForTesting internal fun listenForDozeAmountTransition(scope: CoroutineScope): Job { - return scope.launch { + return scope.launch("$TAG#listenForDozeAmountTransition") { merge( keyguardTransitionInteractor.aodToLockscreenTransition.map { step -> step.copy(value = 1f - step.value) @@ -550,7 +554,7 @@ constructor( */ @VisibleForTesting internal fun listenForAnyStateToAodTransition(scope: CoroutineScope): Job { - return scope.launch { + return scope.launch("$TAG#listenForAnyStateToAodTransition") { keyguardTransitionInteractor .transitionStepsToState(AOD) .filter { it.transitionState == TransitionState.STARTED } @@ -561,7 +565,7 @@ constructor( @VisibleForTesting internal fun listenForDozing(scope: CoroutineScope): Job { - return scope.launch { + return scope.launch("$TAG#listenForDozing") { combine( keyguardInteractor.dozeAmount, keyguardInteractor.isDozing, @@ -626,7 +630,7 @@ constructor( } companion object { - private val TAG = ClockEventController::class.simpleName!! - private val DOZE_TICKRATE_THRESHOLD = 0.99f + private const val TAG = "ClockEventController" + private const val DOZE_TICKRATE_THRESHOLD = 0.99f } } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java index 5b8eb9d3da82..790a8434c229 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java @@ -250,7 +250,6 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS mLargeClockFrame = mView.findViewById(R.id.lockscreen_clock_view_large); } - if (!mOnlyClock) { mDumpManager.unregisterDumpable(getClass().getSimpleName()); // unregister previous mDumpManager.registerDumpable(getClass().getSimpleName(), this); @@ -282,7 +281,9 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS protected void onViewAttached() { mClockRegistry.registerClockChangeListener(mClockChangedListener); setClock(mClockRegistry.createCurrentClock()); - mClockEventController.registerListeners(mView); + if (!MigrateClocksToBlueprint.isEnabled()) { + mClockEventController.registerListeners(mView); + } mKeyguardSmallClockTopMargin = mView.getResources().getDimensionPixelSize(R.dimen.keyguard_clock_top_margin); mKeyguardLargeClockTopMargin = @@ -365,7 +366,9 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS @Override protected void onViewDetached() { mClockRegistry.unregisterClockChangeListener(mClockChangedListener); - mClockEventController.unregisterListeners(); + if (!MigrateClocksToBlueprint.isEnabled()) { + mClockEventController.unregisterListeners(); + } setClock(null); mBgExecutor.execute(() -> { diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java index 424bd0a3e23b..9a9e698e0138 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java @@ -209,6 +209,15 @@ public class DozeLog implements Dumpable { } /** + * Logs cancelation requests for time ticks + * @param isPending is an unschedule request pending? + * @param isTimeTickScheduled is a time tick request scheduled + */ + public void tracePendingUnscheduleTimeTick(boolean isPending, boolean isTimeTickScheduled) { + mLogger.logPendingUnscheduleTimeTick(isPending, isTimeTickScheduled); + } + + /** * Appends keyguard visibility change event to the logs * @param showing whether the keyguard is now showing */ diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt b/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt index 75b8e513c14a..9d6693efffa3 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt @@ -162,6 +162,15 @@ class DozeLogger @Inject constructor( }) } + fun logPendingUnscheduleTimeTick(isPending: Boolean, isTimeTickScheduled: Boolean) { + buffer.log(TAG, INFO, { + bool1 = isPending + bool2 = isTimeTickScheduled + }, { + "Pending unschedule time tick, isPending=$bool1, isTimeTickScheduled:$bool2" + }) + } + fun logDozeStateChanged(state: DozeMachine.State) { buffer.log(TAG, INFO, { str1 = state.name diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java index 34a80e867153..1a855d735a02 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java @@ -26,11 +26,12 @@ import android.os.SystemClock; import android.text.format.Formatter; import android.util.Log; -import com.android.systemui.DejankUtils; +import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.doze.dagger.DozeScope; import com.android.systemui.statusbar.phone.DozeParameters; import com.android.systemui.util.AlarmTimeout; +import com.android.systemui.util.concurrency.DelayableExecutor; import com.android.systemui.util.wakelock.WakeLock; import java.util.Calendar; @@ -52,14 +53,19 @@ public class DozeUi implements DozeMachine.Part { private final boolean mCanAnimateTransition; private final DozeParameters mDozeParameters; private final DozeLog mDozeLog; + private final DelayableExecutor mBgExecutor; + private Runnable mCancelRunnable = null; private long mLastTimeTickElapsed = 0; // If time tick is scheduled and there's not a pending runnable to cancel: - private boolean mTimeTickScheduled; + private volatile boolean mTimeTickScheduled; private final Runnable mCancelTimeTickerRunnable = new Runnable() { @Override public void run() { - mTimeTicker.cancel(); + mDozeLog.tracePendingUnscheduleTimeTick(false, mTimeTickScheduled); + if (!mTimeTickScheduled) { + mTimeTicker.cancel(); + } } }; @@ -67,11 +73,13 @@ public class DozeUi implements DozeMachine.Part { public DozeUi(Context context, AlarmManager alarmManager, WakeLock wakeLock, DozeHost host, @Main Handler handler, DozeParameters params, + @Background DelayableExecutor bgExecutor, DozeLog dozeLog) { mContext = context; mWakeLock = wakeLock; mHost = host; mHandler = handler; + mBgExecutor = bgExecutor; mCanAnimateTransition = !params.getDisplayNeedsBlanking(); mDozeParameters = params; mTimeTicker = new AlarmTimeout(alarmManager, this::onTimeTick, "doze_time_tick", handler); @@ -166,7 +174,6 @@ public class DozeUi implements DozeMachine.Part { return; } mTimeTickScheduled = true; - DejankUtils.removeCallbacks(mCancelTimeTickerRunnable); long time = System.currentTimeMillis(); long delta = roundToNextMinute(time) - System.currentTimeMillis(); @@ -182,7 +189,8 @@ public class DozeUi implements DozeMachine.Part { return; } mTimeTickScheduled = false; - DejankUtils.postAfterTraversal(mCancelTimeTickerRunnable); + mDozeLog.tracePendingUnscheduleTimeTick(true, mTimeTickScheduled); + mBgExecutor.execute(mCancelTimeTickerRunnable); } private void verifyLastTimeTick() { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt index 30beca7d00e1..9f7e0d43c3b5 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt @@ -41,6 +41,7 @@ import com.android.keyguard.dagger.KeyguardStatusViewComponent import com.android.systemui.CoreStartable import com.android.systemui.common.ui.ConfigurationState import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.deviceentry.domain.interactor.DeviceEntryHapticsInteractor import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor @@ -72,6 +73,7 @@ import com.android.systemui.statusbar.phone.ScreenOffAnimationController import com.android.systemui.temporarydisplay.chipbar.ChipbarCoordinator import dagger.Lazy import javax.inject.Inject +import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.DisposableHandle import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -108,6 +110,7 @@ constructor( private val keyguardBlueprintViewBinder: KeyguardBlueprintViewBinder, private val clockInteractor: KeyguardClockInteractor, private val keyguardViewMediator: KeyguardViewMediator, + @Main private val mainImmediateDispatcher: CoroutineDispatcher, ) : CoreStartable { private var rootViewHandle: DisposableHandle? = null @@ -211,6 +214,7 @@ constructor( vibratorHelper, falsingManager, keyguardViewMediator, + mainImmediateDispatcher, ) } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt index 8cc077992f7f..4c54bfd3a17c 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt @@ -22,6 +22,7 @@ import android.animation.ValueAnimator.AnimatorUpdateListener import android.annotation.FloatRange import android.os.Trace import android.util.Log +import com.android.app.tracing.coroutines.withContext import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.keyguard.shared.model.KeyguardState @@ -41,7 +42,6 @@ import kotlinx.coroutines.flow.asSharedFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.filter -import kotlinx.coroutines.withContext /** * The source of truth for all keyguard transitions. @@ -150,7 +150,7 @@ constructor( _currentTransitionInfo.value = info // Animators must be started on the main thread. - return withContext(mainDispatcher) { + return withContext("$TAG#startTransition", mainDispatcher) { if (lastStep.from == info.from && lastStep.to == info.to) { Log.i(TAG, "Duplicate call to start the transition, rejecting: $info") return@withContext null diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt index 4bf5200a507f..f359525fbe89 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt @@ -18,6 +18,7 @@ package com.android.systemui.keyguard.domain.interactor import android.animation.ValueAnimator import com.android.app.animation.Interpolators +import com.android.app.tracing.coroutines.launch import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dagger.qualifiers.Main @@ -33,7 +34,6 @@ import kotlin.time.Duration.Companion.milliseconds import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.debounce -import kotlinx.coroutines.launch @SysUISingleton class FromAodTransitionInteractor @@ -72,7 +72,7 @@ constructor( // Use PowerInteractor's wakefulness, which is the earliest wake signal available. We // have all of the information we need at this time to make a decision about where to // transition. - scope.launch { + scope.launch("$TAG#listenForAodToAwake") { powerInteractor.detailedWakefulness .filterRelevantKeyguardStateAnd { wakefulness -> wakefulness.isAwake() } .sample( @@ -150,7 +150,7 @@ constructor( return } - scope.launch { + scope.launch("$TAG#listenForAodToOccluded") { keyguardInteractor.isKeyguardOccluded .filterRelevantKeyguardStateAnd { isOccluded -> isOccluded } .collect { @@ -168,7 +168,7 @@ constructor( * PRIMARY_BOUNCER. */ private fun listenForAodToPrimaryBouncer() { - scope.launch { + scope.launch("$TAG#listenForAodToPrimaryBouncer") { keyguardInteractor.primaryBouncerShowing .filterRelevantKeyguardStateAnd { primaryBouncerShowing -> primaryBouncerShowing } .collect { startTransitionTo(KeyguardState.PRIMARY_BOUNCER) } @@ -181,7 +181,7 @@ constructor( return } - scope.launch { + scope.launch("$TAG#listenForAodToGone") { powerInteractor.isAwake .debounce(50L) .filterRelevantKeyguardState() @@ -209,7 +209,7 @@ constructor( * AOD. */ fun dismissAod() { - scope.launch { startTransitionTo(KeyguardState.GONE) } + scope.launch("$TAG#dismissAod") { startTransitionTo(KeyguardState.GONE) } } override fun getDefaultAnimatorForTransitionsToState(toState: KeyguardState): ValueAnimator { @@ -224,7 +224,7 @@ constructor( } companion object { - const val TAG = "FromAodTransitionInteractor" + private const val TAG = "FromAodTransitionInteractor" private val DEFAULT_DURATION = 500.milliseconds val TO_LOCKSCREEN_DURATION = 500.milliseconds val TO_GONE_DURATION = DEFAULT_DURATION diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractor.kt index 4a8818207568..c2c095bb9574 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractor.kt @@ -18,6 +18,7 @@ package com.android.systemui.keyguard.domain.interactor import android.animation.ValueAnimator import com.android.app.animation.Interpolators +import com.android.app.tracing.coroutines.launch import com.android.systemui.communal.domain.interactor.CommunalInteractor import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background @@ -68,13 +69,13 @@ constructor( } fun showKeyguard() { - scope.launch { startTransitionTo(KeyguardState.LOCKSCREEN) } + scope.launch("$TAG#showKeyguard") { startTransitionTo(KeyguardState.LOCKSCREEN) } } // Primarily for when the user chooses to lock down the device private fun listenForGoneToLockscreenOrHub() { if (KeyguardWmStateRefactor.isEnabled) { - scope.launch { + scope.launch("$TAG#listenForGoneToLockscreenOrHub") { biometricSettingsRepository.isCurrentUserInLockdown .distinctUntilChanged() .filterRelevantKeyguardStateAnd { inLockdown -> inLockdown } @@ -90,7 +91,7 @@ constructor( } } } else { - scope.launch { + scope.launch("$TAG#listenForGoneToLockscreenOrHub") { keyguardInteractor.isKeyguardShowing .filterRelevantKeyguardStateAnd { isKeyguardShowing -> isKeyguardShowing } .sample(communalInteractor.isIdleOnCommunal, ::Pair) @@ -108,7 +109,7 @@ constructor( } private fun listenForGoneToDreamingLockscreenHosted() { - scope.launch { + scope.launch("$TAG#listenForGoneToDreamingLockscreenHosted") { keyguardInteractor.isActiveDreamLockscreenHosted .filterRelevantKeyguardStateAnd { isActiveDreamLockscreenHosted -> isActiveDreamLockscreenHosted @@ -118,7 +119,7 @@ constructor( } private fun listenForGoneToDreaming() { - scope.launch { + scope.launch("$TAG#listenForGoneToDreaming") { keyguardInteractor.isAbleToDream .sample(keyguardInteractor.isActiveDreamLockscreenHosted, ::Pair) .filterRelevantKeyguardStateAnd { (isAbleToDream, isActiveDreamLockscreenHosted) -> @@ -129,7 +130,7 @@ constructor( } private fun listenForGoneToAodOrDozing() { - scope.launch { + scope.launch("$TAG#listenForGoneToAodOrDozing") { listenForSleepTransition( modeOnCanceledFromStartedStep = { TransitionModeOnCanceled.RESET }, ) @@ -151,6 +152,7 @@ constructor( } companion object { + private const val TAG = "FromGoneTransitionInteractor" private val DEFAULT_DURATION = 500.milliseconds val TO_DREAMING_DURATION = 933.milliseconds val TO_AOD_DURATION = 1300.milliseconds diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt index b35faf753ba9..56261e0865e1 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt @@ -19,6 +19,7 @@ package com.android.systemui.keyguard.domain.interactor import android.animation.ValueAnimator import android.util.MathUtils import com.android.app.animation.Interpolators +import com.android.app.tracing.coroutines.launch import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dagger.qualifiers.Main @@ -119,7 +120,7 @@ constructor( } val invalidFromStates = setOf(KeyguardState.AOD, KeyguardState.DOZING) - scope.launch { + scope.launch("$TAG#listenForLockscreenToDreaming") { keyguardInteractor.isAbleToDream .filterRelevantKeyguardState() .sampleCombine( @@ -149,7 +150,7 @@ constructor( } private fun listenForLockscreenToPrimaryBouncer() { - scope.launch { + scope.launch("$TAG#listenForLockscreenToPrimaryBouncer") { keyguardInteractor.primaryBouncerShowing .filterRelevantKeyguardStateAnd { isBouncerShowing -> isBouncerShowing } .collect { @@ -162,7 +163,7 @@ constructor( } private fun listenForLockscreenToAlternateBouncer() { - scope.launch { + scope.launch("$TAG#listenForLockscreenToAlternateBouncer") { keyguardInteractor.alternateBouncerShowing .filterRelevantKeyguardStateAnd { isAlternateBouncerShowing -> isAlternateBouncerShowing @@ -174,7 +175,7 @@ constructor( /* Starts transitions when manually dragging up the bouncer from the lockscreen. */ private fun listenForLockscreenToPrimaryBouncerDragging() { var transitionId: UUID? = null - scope.launch { + scope.launch("$TAG#listenForLockscreenToPrimaryBouncerDragging") { shadeRepository.legacyShadeExpansion .sampleCombine( startedKeyguardTransitionStep, @@ -258,7 +259,7 @@ constructor( } fun dismissKeyguard() { - scope.launch { startTransitionTo(KeyguardState.GONE) } + scope.launch("$TAG#dismissKeyguard") { startTransitionTo(KeyguardState.GONE) } } private fun listenForLockscreenToGone() { @@ -266,7 +267,7 @@ constructor( return } - scope.launch { + scope.launch("$TAG#listenForLockscreenToGone") { keyguardInteractor.isKeyguardGoingAway .filterRelevantKeyguardStateAnd { isKeyguardGoingAway -> isKeyguardGoingAway } .collect { @@ -281,7 +282,7 @@ constructor( private fun listenForLockscreenToGoneDragging() { if (KeyguardWmStateRefactor.isEnabled) { // When the refactor is enabled, we no longer use isKeyguardGoingAway. - scope.launch { + scope.launch("$TAG#listenForLockscreenToGoneDragging") { swipeToDismissInteractor.dismissFling .filterNotNull() .filterRelevantKeyguardState() @@ -292,7 +293,7 @@ constructor( private fun listenForLockscreenToOccludedOrDreaming() { if (KeyguardWmStateRefactor.isEnabled) { - scope.launch { + scope.launch("$TAG#listenForLockscreenToOccludedOrDreaming") { keyguardOcclusionInteractor.showWhenLockedActivityInfo .filterRelevantKeyguardStateAnd { it.isOnTop } .collect { taskInfo -> @@ -306,7 +307,7 @@ constructor( } } } else { - scope.launch { + scope.launch("$TAG#listenForLockscreenToOccludedOrDreaming") { keyguardInteractor.isKeyguardOccluded .filterRelevantKeyguardStateAnd { isOccluded -> isOccluded } .collect { startTransitionTo(KeyguardState.OCCLUDED) } @@ -315,7 +316,7 @@ constructor( } private fun listenForLockscreenToAodOrDozing() { - scope.launch { + scope.launch("$TAG#listenForLockscreenToAodOrDozing") { listenForSleepTransition( modeOnCanceledFromStartedStep = { startedStep -> if ( @@ -367,7 +368,7 @@ constructor( } companion object { - const val TAG = "FromLockscreenTransitionInteractor" + private const val TAG = "FromLockscreenTransitionInteractor" private val DEFAULT_DURATION = 400.milliseconds val TO_DOZING_DURATION = 500.milliseconds val TO_DREAMING_DURATION = 933.milliseconds diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt index 851eafa1a4df..f128a80191df 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt @@ -49,6 +49,7 @@ import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.shade.data.repository.ShadeRepository import com.android.systemui.statusbar.CommandQueue import com.android.systemui.statusbar.notification.stack.domain.interactor.SharedNotificationContainerInteractor +import com.android.systemui.util.kotlin.Utils.Companion.sample as sampleCombine import com.android.systemui.util.kotlin.sample import javax.inject.Inject import javax.inject.Provider @@ -279,12 +280,16 @@ constructor( * signal should be sent directly to transitions. */ val dismissAlpha: Flow<Float?> = - combine( - shadeRepository.legacyShadeExpansion, + shadeRepository.legacyShadeExpansion + .filter { it < 1f } + .sampleCombine( statusBarState, keyguardTransitionInteractor.currentKeyguardState, isKeyguardDismissible, - ) { legacyShadeExpansion, statusBarState, currentKeyguardState, isKeyguardDismissible -> + ) + .map { + (legacyShadeExpansion, statusBarState, currentKeyguardState, isKeyguardDismissible) + -> if ( statusBarState == StatusBarState.KEYGUARD && isKeyguardDismissible && diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerMessageAreaViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerMessageAreaViewBinder.kt index 9186dde9a9bf..fe5f632c0b6a 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerMessageAreaViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerMessageAreaViewBinder.kt @@ -18,6 +18,7 @@ package com.android.systemui.keyguard.ui.binder import androidx.lifecycle.Lifecycle import androidx.lifecycle.repeatOnLifecycle +import com.android.app.tracing.coroutines.launch import com.android.keyguard.AuthKeyguardMessageArea import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerMessageAreaViewModel import com.android.systemui.lifecycle.repeatWhenAttached @@ -36,14 +37,18 @@ object AlternateBouncerMessageAreaViewBinder { view.setIsVisible(true) view.repeatWhenAttached { repeatOnLifecycle(Lifecycle.State.STARTED) { - viewModel.message.collect { biometricMsg -> - if (biometricMsg == null) { - view.setMessage("", true) - } else { - view.setMessage(biometricMsg.message, true) + launch("$TAG#viewModel.message") { + viewModel.message.collect { biometricMsg -> + if (biometricMsg == null) { + view.setMessage("", true) + } else { + view.setMessage(biometricMsg.message, true) + } } } } } } + + private const val TAG = "AlternateBouncerMessageAreaViewBinder" } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerUdfpsViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerUdfpsViewBinder.kt index a861a8782ef9..9dc77d3dc9d3 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerUdfpsViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerUdfpsViewBinder.kt @@ -21,12 +21,12 @@ import android.content.res.ColorStateList import android.view.View import androidx.lifecycle.Lifecycle import androidx.lifecycle.repeatOnLifecycle +import com.android.app.tracing.coroutines.launch import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor import com.android.systemui.keyguard.ui.view.DeviceEntryIconView import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerUdfpsIconViewModel import com.android.systemui.lifecycle.repeatWhenAttached import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.launch @ExperimentalCoroutinesApi object AlternateBouncerUdfpsViewBinder { @@ -46,13 +46,13 @@ object AlternateBouncerUdfpsViewBinder { view.repeatWhenAttached { repeatOnLifecycle(Lifecycle.State.STARTED) { view.alpha = 0f - launch { + launch("$TAG#viewModel.accessibilityDelegateHint") { viewModel.accessibilityDelegateHint.collect { hint -> view.accessibilityHintType = hint } } - launch { viewModel.alpha.collect { view.alpha = it } } + launch("$TAG#viewModel.alpha") { viewModel.alpha.collect { view.alpha = it } } } } @@ -77,13 +77,17 @@ object AlternateBouncerUdfpsViewBinder { bgView.visibility = View.VISIBLE bgView.repeatWhenAttached { repeatOnLifecycle(Lifecycle.State.STARTED) { - launch { + launch("$TAG#viewModel.bgColor") { viewModel.bgColor.collect { color -> bgView.imageTintList = ColorStateList.valueOf(color) } } - launch { viewModel.bgAlpha.collect { alpha -> bgView.alpha = alpha } } + launch("$TAG#viewModel.bgAlpha") { + viewModel.bgAlpha.collect { alpha -> bgView.alpha = alpha } + } } } } + + private const val TAG = "AlternateBouncerUdfpsViewBinder" } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinder.kt index 1eea556f235d..53f013275451 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinder.kt @@ -28,6 +28,7 @@ import androidx.constraintlayout.widget.ConstraintLayout import androidx.constraintlayout.widget.ConstraintSet import androidx.lifecycle.Lifecycle import androidx.lifecycle.repeatOnLifecycle +import com.android.app.tracing.coroutines.launch import com.android.systemui.CoreStartable import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application @@ -46,7 +47,6 @@ import dagger.Lazy import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.launch /** * When necessary, adds the alternate bouncer window above most other windows (including the @@ -92,7 +92,7 @@ constructor( if (!DeviceEntryUdfpsRefactor.isEnabled) { return } - applicationScope.launch { + applicationScope.launch("$TAG#alternateBouncerWindowViewModel") { alternateBouncerWindowViewModel.get().alternateBouncerWindowRequired.collect { addAlternateBouncerWindowView -> if (addAlternateBouncerWindowView) { @@ -186,7 +186,7 @@ constructor( val tapGestureDetector = alternateBouncerDependencies.tapGestureDetector view.repeatWhenAttached { alternateBouncerViewContainer -> repeatOnLifecycle(Lifecycle.State.STARTED) { - launch { + launch("$TAG#viewModel.registerForDismissGestures") { viewModel.registerForDismissGestures.collect { registerForDismissGestures -> if (registerForDismissGestures) { swipeUpAnywhereGestureHandler.addOnGestureDetectedCallback(swipeTag) { _ @@ -205,9 +205,13 @@ constructor( } } - launch { viewModel.scrimAlpha.collect { scrim.viewAlpha = it } } + launch("$TAG#viewModel.scrimAlpha") { + viewModel.scrimAlpha.collect { scrim.viewAlpha = it } + } - launch { viewModel.scrimColor.collect { scrim.tint = it } } + launch("$TAG#viewModel.scrimColor") { + viewModel.scrimColor.collect { scrim.tint = it } + } } } } @@ -219,7 +223,7 @@ constructor( ) { view.repeatWhenAttached { repeatOnLifecycle(Lifecycle.State.CREATED) { - launch { + launch("$TAG#udfpsIconViewModel.iconLocation") { udfpsIconViewModel.iconLocation.collect { iconLocation -> // add UDFPS a11y overlay val udfpsA11yOverlayViewId = @@ -292,7 +296,9 @@ constructor( } } } + companion object { + private const val TAG = "AlternateBouncerViewBinder" + private const val swipeTag = "AlternateBouncer-SWIPE" + private const val tapTag = "AlternateBouncer-TAP" + } } - -private const val swipeTag = "AlternateBouncer-SWIPE" -private const val tapTag = "AlternateBouncer-TAP" diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/DeviceEntryIconViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/DeviceEntryIconViewBinder.kt index f46a207b273a..e423fe0bd8a0 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/DeviceEntryIconViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/DeviceEntryIconViewBinder.kt @@ -25,6 +25,7 @@ import android.view.View import androidx.core.view.isInvisible import androidx.lifecycle.Lifecycle import androidx.lifecycle.repeatOnLifecycle +import com.android.app.tracing.coroutines.launch import com.android.systemui.common.ui.view.LongPressHandlingView import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor import com.android.systemui.keyguard.ui.view.DeviceEntryIconView @@ -34,13 +35,15 @@ import com.android.systemui.keyguard.ui.viewmodel.DeviceEntryIconViewModel import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.plugins.FalsingManager import com.android.systemui.statusbar.VibratorHelper +import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.launch @ExperimentalCoroutinesApi object DeviceEntryIconViewBinder { + private const val TAG = "DeviceEntryIconViewBinder" + /** * Updates UI for: * - device entry containing view (parent view for the below views) @@ -58,6 +61,7 @@ object DeviceEntryIconViewBinder { bgViewModel: DeviceEntryBackgroundViewModel, falsingManager: FalsingManager, vibratorHelper: VibratorHelper, + mainImmediateDispatcher: CoroutineDispatcher, ) { DeviceEntryUdfpsRefactor.isUnexpectedlyInLegacyMode() val longPressHandlingView = view.longPressHandlingView @@ -73,31 +77,33 @@ object DeviceEntryIconViewBinder { view, HapticFeedbackConstants.CONFIRM, ) - applicationScope.launch { viewModel.onLongPress() } + applicationScope.launch("$TAG#viewModel.onLongPress") { + viewModel.onLongPress() + } } } - view.repeatWhenAttached { + view.repeatWhenAttached(mainImmediateDispatcher) { // Repeat on CREATED so that the view will always observe the entire // GONE => AOD transition (even though the view may not be visible until the middle // of the transition. repeatOnLifecycle(Lifecycle.State.CREATED) { - launch { + launch("$TAG#viewModel.isVisible") { viewModel.isVisible.collect { isVisible -> longPressHandlingView.isInvisible = !isVisible } } - launch { + launch("$TAG#viewModel.isLongPressEnabled") { viewModel.isLongPressEnabled.collect { isEnabled -> longPressHandlingView.setLongPressHandlingEnabled(isEnabled) } } - launch { + launch("$TAG#viewModel.accessibilityDelegateHint") { viewModel.accessibilityDelegateHint.collect { hint -> view.accessibilityHintType = hint } } - launch { + launch("$TAG#viewModel.useBackgroundProtection") { viewModel.useBackgroundProtection.collect { useBackgroundProtection -> if (useBackgroundProtection) { bgView.visibility = View.VISIBLE @@ -106,7 +112,7 @@ object DeviceEntryIconViewBinder { } } } - launch { + launch("$TAG#viewModel.burnInOffsets") { viewModel.burnInOffsets.collect { burnInOffsets -> view.translationX = burnInOffsets.x.toFloat() view.translationY = burnInOffsets.y.toFloat() @@ -114,15 +120,17 @@ object DeviceEntryIconViewBinder { } } - launch { viewModel.deviceEntryViewAlpha.collect { alpha -> view.alpha = alpha } } + launch("$TAG#viewModel.deviceEntryViewAlpha") { + viewModel.deviceEntryViewAlpha.collect { alpha -> view.alpha = alpha } + } } } - fgIconView.repeatWhenAttached { + fgIconView.repeatWhenAttached(mainImmediateDispatcher) { repeatOnLifecycle(Lifecycle.State.STARTED) { // Start with an empty state fgIconView.setImageState(StateSet.NOTHING, /* merge */ false) - launch { + launch("$TAG#fgViewModel.viewModel") { fgViewModel.viewModel.collect { viewModel -> fgIconView.setImageState( view.getIconState(viewModel.type, viewModel.useAodVariant), @@ -142,8 +150,10 @@ object DeviceEntryIconViewBinder { bgView.repeatWhenAttached { repeatOnLifecycle(Lifecycle.State.CREATED) { - launch { bgViewModel.alpha.collect { alpha -> bgView.alpha = alpha } } - launch { + launch("$TAG#bgViewModel.alpha") { + bgViewModel.alpha.collect { alpha -> bgView.alpha = alpha } + } + launch("$TAG#bgViewModel.color") { bgViewModel.color.collect { color -> bgView.imageTintList = ColorStateList.valueOf(color) } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBlueprintViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBlueprintViewBinder.kt index 7e3ddf92c530..b5d61773d9af 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBlueprintViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBlueprintViewBinder.kt @@ -26,6 +26,7 @@ import androidx.constraintlayout.widget.ConstraintLayout import androidx.constraintlayout.widget.ConstraintSet import androidx.lifecycle.Lifecycle import androidx.lifecycle.repeatOnLifecycle +import com.android.app.tracing.coroutines.launch import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.keyguard.KeyguardBottomAreaRefactor @@ -39,7 +40,6 @@ import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.res.R import javax.inject.Inject import kotlin.math.max -import kotlinx.coroutines.launch private const val TAG = "KeyguardBlueprintViewBinder" private const val DEBUG = false @@ -90,7 +90,7 @@ constructor( ) { constraintLayout.repeatWhenAttached { repeatOnLifecycle(Lifecycle.State.CREATED) { - launch { + launch("$TAG#viewModel.blueprint") { viewModel.blueprint.collect { blueprint -> Trace.beginSection("KeyguardBlueprintViewBinder#applyBlueprint") val prevBluePrint = viewModel.currentBluePrint @@ -137,7 +137,7 @@ constructor( } } - launch { + launch("$TAG#viewModel.refreshTransition") { viewModel.refreshTransition.collect { transition -> Trace.beginSection("KeyguardBlueprintViewBinder#refreshTransition") val cs = diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt index 397cbe5b3e5d..660a650fb916 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt @@ -36,6 +36,7 @@ import androidx.core.view.updateLayoutParams import androidx.lifecycle.Lifecycle import androidx.lifecycle.repeatOnLifecycle import com.android.app.animation.Interpolators +import com.android.app.tracing.coroutines.launch import com.android.settingslib.Utils import com.android.systemui.animation.ActivityTransitionAnimator import com.android.systemui.animation.Expandable @@ -61,7 +62,6 @@ import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.map -import kotlinx.coroutines.launch /** * Binds a keyguard bottom area view to its view-model. @@ -77,6 +77,7 @@ object KeyguardBottomAreaViewBinder { private const val EXIT_DOZE_BUTTON_REVEAL_ANIMATION_DURATION_MS = 250L private const val SCALE_SELECTED_BUTTON = 1.23f private const val DIM_ALPHA = 0.3f + private const val TAG = "KeyguardBottomAreaViewBinder" /** * Defines interface for an object that acts as the binding between the view and its view-model. @@ -171,7 +172,7 @@ object KeyguardBottomAreaViewBinder { view.repeatWhenAttached { repeatOnLifecycle(Lifecycle.State.STARTED) { // If updated, be sure to update [KeyguardQuickAffordanceViewBinder.kt] - launch { + launch("$TAG#viewModel.startButton") { viewModel.startButton.collect { buttonModel -> updateButton( view = startButton, @@ -184,7 +185,7 @@ object KeyguardBottomAreaViewBinder { } // If updated, be sure to update [KeyguardQuickAffordanceViewBinder.kt] - launch { + launch("$TAG#viewModel.endButton") { viewModel.endButton.collect { buttonModel -> updateButton( view = endButton, @@ -196,7 +197,7 @@ object KeyguardBottomAreaViewBinder { } } - launch { + launch("$TAG#viewModel.isOverlayContainerVisible") { viewModel.isOverlayContainerVisible.collect { isVisible -> overlayContainer.visibility = if (isVisible) { @@ -207,7 +208,7 @@ object KeyguardBottomAreaViewBinder { } } - launch { + launch("$TAG#viewModel.alpha") { viewModel.alpha.collect { alpha -> ambientIndicationArea?.apply { this.importantForAccessibility = @@ -222,7 +223,7 @@ object KeyguardBottomAreaViewBinder { } // If updated, be sure to update [KeyguardQuickAffordanceViewBinder.kt] - launch { + launch("$TAG#updateButtonAlpha") { updateButtonAlpha( view = startButton, viewModel = viewModel.startButton, @@ -231,7 +232,7 @@ object KeyguardBottomAreaViewBinder { } // If updated, be sure to update [KeyguardQuickAffordanceViewBinder.kt] - launch { + launch("$TAG#updateButtonAlpha") { updateButtonAlpha( view = endButton, viewModel = viewModel.endButton, @@ -239,13 +240,13 @@ object KeyguardBottomAreaViewBinder { ) } - launch { + launch("$TAG#viewModel.indicationAreaTranslationX") { viewModel.indicationAreaTranslationX.collect { translationX -> ambientIndicationArea?.translationX = translationX } } - launch { + launch("$TAG#viewModel.indicationAreaTranslationY") { configurationBasedDimensions .map { it.defaultBurnInPreventionYOffsetPx } .flatMapLatest { defaultBurnInOffsetY -> @@ -257,7 +258,7 @@ object KeyguardBottomAreaViewBinder { } // If updated, be sure to update [KeyguardQuickAffordanceViewBinder.kt] - launch { + launch("$TAG#startButton.updateLayoutParams<ViewGroup") { configurationBasedDimensions.collect { dimensions -> startButton.updateLayoutParams<ViewGroup.LayoutParams> { width = dimensions.buttonSizePx.width @@ -270,7 +271,7 @@ object KeyguardBottomAreaViewBinder { } } - launch { + launch("$TAG#viewModel.settingsMenuViewModel") { viewModel.settingsMenuViewModel.isVisible.distinctUntilChanged().collect { isVisible -> settingsMenu.animateVisibility(visible = isVisible) @@ -297,7 +298,7 @@ object KeyguardBottomAreaViewBinder { // shows up in the Wallpaper Picker app. If we do that, then the // settings menu should never be visible. if (activityStarter != null) { - launch { + launch("$TAG#viewModel.settingsMenuViewModel") { viewModel.settingsMenuViewModel.shouldOpenSettings .filter { it } .collect { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardClockViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardClockViewBinder.kt index 6255f0d44609..1b06a69213b9 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardClockViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardClockViewBinder.kt @@ -26,6 +26,7 @@ import androidx.constraintlayout.widget.ConstraintLayout import androidx.constraintlayout.widget.ConstraintSet import androidx.lifecycle.Lifecycle import androidx.lifecycle.repeatOnLifecycle +import com.android.app.tracing.coroutines.launch import com.android.keyguard.KeyguardClockSwitch.LARGE import com.android.keyguard.KeyguardClockSwitch.SMALL import com.android.systemui.keyguard.MigrateClocksToBlueprint @@ -37,10 +38,10 @@ import com.android.systemui.keyguard.ui.viewmodel.KeyguardClockViewModel import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.plugins.clocks.ClockController import com.android.systemui.shared.clocks.DEFAULT_CLOCK_ID -import kotlinx.coroutines.launch +import kotlinx.coroutines.DisposableHandle object KeyguardClockViewBinder { - private val TAG = KeyguardClockViewBinder::class.simpleName!! + private const val TAG = "KeyguardClockViewBinder" // When changing to new clock, we need to remove old clock views from burnInLayer private var lastClock: ClockController? = null @JvmStatic @@ -50,15 +51,12 @@ object KeyguardClockViewBinder { viewModel: KeyguardClockViewModel, keyguardClockInteractor: KeyguardClockInteractor, blueprintInteractor: KeyguardBlueprintInteractor, - ) { - keyguardRootView.repeatWhenAttached { - repeatOnLifecycle(Lifecycle.State.CREATED) { - keyguardClockInteractor.clockEventController.registerListeners(keyguardRootView) - } - } - keyguardRootView.repeatWhenAttached { + ): DisposableHandle { + keyguardClockInteractor.clockEventController.registerListeners(keyguardRootView) + + return keyguardRootView.repeatWhenAttached { repeatOnLifecycle(Lifecycle.State.CREATED) { - launch { + launch("$TAG#viewModel.currentClock") { if (!MigrateClocksToBlueprint.isEnabled) return@launch viewModel.currentClock.collect { currentClock -> cleanupClockViews(currentClock, keyguardRootView, viewModel.burnInLayer) @@ -67,14 +65,14 @@ object KeyguardClockViewBinder { applyConstraints(clockSection, keyguardRootView, true) } } - launch { + launch("$TAG#viewModel.clockSize") { if (!MigrateClocksToBlueprint.isEnabled) return@launch viewModel.clockSize.collect { updateBurnInLayer(keyguardRootView, viewModel) blueprintInteractor.refreshBlueprint(Type.ClockSize) } } - launch { + launch("$TAG#viewModel.clockShouldBeCentered") { if (!MigrateClocksToBlueprint.isEnabled) return@launch viewModel.clockShouldBeCentered.collect { clockShouldBeCentered -> viewModel.currentClock.value?.let { @@ -91,7 +89,7 @@ object KeyguardClockViewBinder { } } } - launch { + launch("$TAG#viewModel.isAodIconsVisible") { if (!MigrateClocksToBlueprint.isEnabled) return@launch viewModel.isAodIconsVisible.collect { isAodIconsVisible -> viewModel.currentClock.value?.let { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardIndicationAreaBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardIndicationAreaBinder.kt index 267d68e5e5e1..23c2491813f7 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardIndicationAreaBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardIndicationAreaBinder.kt @@ -22,6 +22,7 @@ import android.view.ViewGroup import android.widget.TextView import androidx.lifecycle.Lifecycle import androidx.lifecycle.repeatOnLifecycle +import com.android.app.tracing.coroutines.launch import com.android.systemui.keyguard.KeyguardBottomAreaRefactor import com.android.systemui.keyguard.MigrateClocksToBlueprint import com.android.systemui.keyguard.ui.viewmodel.KeyguardIndicationAreaViewModel @@ -34,7 +35,6 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.map -import kotlinx.coroutines.launch /** * Binds a keyguard indication area view to its view-model. @@ -66,7 +66,7 @@ object KeyguardIndicationAreaBinder { val disposableHandle = view.repeatWhenAttached { repeatOnLifecycle(Lifecycle.State.STARTED) { - launch { + launch("$TAG#viewModel.alpha") { // Do not independently apply alpha, as [KeyguardRootViewModel] should work // for this and all its children if ( @@ -77,13 +77,13 @@ object KeyguardIndicationAreaBinder { } } - launch { + launch("$TAG#viewModel.indicationAreaTranslationX") { viewModel.indicationAreaTranslationX.collect { translationX -> view.translationX = translationX } } - launch { + launch("$TAG#viewModel.isIndicationAreaPadded") { combine( viewModel.isIndicationAreaPadded, configurationBasedDimensions.map { it.indicationAreaPaddingPx }, @@ -97,7 +97,7 @@ object KeyguardIndicationAreaBinder { .collect { paddingPx -> view.setPadding(paddingPx, 0, paddingPx, 0) } } - launch { + launch("$TAG#viewModel.indicationAreaTranslationY") { configurationBasedDimensions .map { it.defaultBurnInPreventionYOffsetPx } .flatMapLatest { defaultBurnInOffsetY -> @@ -106,7 +106,7 @@ object KeyguardIndicationAreaBinder { .collect { translationY -> view.translationY = translationY } } - launch { + launch("$TAG#indicationText.setTextSize") { configurationBasedDimensions.collect { dimensions -> indicationText.setTextSize( TypedValue.COMPLEX_UNIT_PX, @@ -119,7 +119,7 @@ object KeyguardIndicationAreaBinder { } } - launch { + launch("$TAG#viewModel.configurationChange") { viewModel.configurationChange.collect { configurationBasedDimensions.value = loadFromResources(view) } @@ -147,4 +147,6 @@ object KeyguardIndicationAreaBinder { val indicationAreaPaddingPx: Int, val indicationTextSizePx: Int, ) + + private const val TAG = "KeyguardIndicationAreaBinder" } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardLongPressViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardLongPressViewBinder.kt index 9cc503c07955..09fe067f7724 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardLongPressViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardLongPressViewBinder.kt @@ -20,11 +20,11 @@ package com.android.systemui.keyguard.ui.binder import android.view.View import androidx.lifecycle.Lifecycle import androidx.lifecycle.repeatOnLifecycle +import com.android.app.tracing.coroutines.launch import com.android.systemui.common.ui.view.LongPressHandlingView import com.android.systemui.keyguard.ui.viewmodel.KeyguardLongPressViewModel import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.plugins.FalsingManager -import kotlinx.coroutines.launch object KeyguardLongPressViewBinder { /** @@ -64,7 +64,7 @@ object KeyguardLongPressViewBinder { view.repeatWhenAttached { repeatOnLifecycle(Lifecycle.State.STARTED) { - launch { + launch("$TAG#viewModel.isLongPressHandlingEnabled") { viewModel.isLongPressHandlingEnabled.collect { isEnabled -> view.setLongPressHandlingEnabled(isEnabled) } @@ -72,4 +72,6 @@ object KeyguardLongPressViewBinder { } } } + + private const val TAG = "KeyguardLongPressViewBinder" } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardPreviewClockViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardPreviewClockViewBinder.kt index 5906cfdda57e..1382468ce7d3 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardPreviewClockViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardPreviewClockViewBinder.kt @@ -33,6 +33,7 @@ import androidx.constraintlayout.widget.ConstraintSet.TOP import androidx.core.view.isVisible import androidx.lifecycle.Lifecycle import androidx.lifecycle.repeatOnLifecycle +import com.android.app.tracing.coroutines.launch import com.android.systemui.customization.R as customizationR import com.android.systemui.keyguard.shared.model.SettingsClockSize import com.android.systemui.keyguard.ui.preview.KeyguardPreviewRenderer @@ -44,7 +45,6 @@ import com.android.systemui.plugins.clocks.ClockController import com.android.systemui.res.R import com.android.systemui.util.Utils import kotlin.reflect.KSuspendFunction1 -import kotlinx.coroutines.launch /** Binder for the small clock view, large clock view. */ object KeyguardPreviewClockViewBinder { @@ -56,13 +56,17 @@ object KeyguardPreviewClockViewBinder { ) { largeClockHostView.repeatWhenAttached { repeatOnLifecycle(Lifecycle.State.STARTED) { - viewModel.isLargeClockVisible.collect { largeClockHostView.isVisible = it } + launch("$TAG#viewModel.isLargeClockVisible") { + viewModel.isLargeClockVisible.collect { largeClockHostView.isVisible = it } + } } } smallClockHostView.repeatWhenAttached { repeatOnLifecycle(Lifecycle.State.STARTED) { - viewModel.isSmallClockVisible.collect { smallClockHostView.isVisible = it } + launch("$TAG#viewModel.isSmallClockVisible") { + viewModel.isSmallClockVisible.collect { smallClockHostView.isVisible = it } + } } } } @@ -76,7 +80,7 @@ object KeyguardPreviewClockViewBinder { ) { rootView.repeatWhenAttached { repeatOnLifecycle(Lifecycle.State.STARTED) { - launch { + launch("$TAG#viewModel.previewClock") { var lastClock: ClockController? = null viewModel.previewClock.collect { currentClock -> lastClock?.let { clock -> @@ -207,4 +211,5 @@ object KeyguardPreviewClockViewBinder { private const val DATE_WEATHER_VIEW_HEIGHT = "date_weather_view_height" private const val ENHANCED_SMARTSPACE_HEIGHT = "enhanced_smartspace_height" + private const val TAG = "KeyguardPreviewClockViewBinder" } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardPreviewSmartspaceViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardPreviewSmartspaceViewBinder.kt index f5d538c32217..49ae35a43c23 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardPreviewSmartspaceViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardPreviewSmartspaceViewBinder.kt @@ -22,10 +22,10 @@ import android.view.View import androidx.core.view.isInvisible import androidx.lifecycle.Lifecycle import androidx.lifecycle.repeatOnLifecycle +import com.android.app.tracing.coroutines.launch import com.android.systemui.keyguard.shared.model.SettingsClockSize import com.android.systemui.keyguard.ui.viewmodel.KeyguardPreviewSmartspaceViewModel import com.android.systemui.lifecycle.repeatWhenAttached -import kotlinx.coroutines.launch /** Binder for the small clock view, large clock view and smartspace. */ object KeyguardPreviewSmartspaceViewBinder { @@ -39,7 +39,7 @@ object KeyguardPreviewSmartspaceViewBinder { ) { smartspace.repeatWhenAttached { repeatOnLifecycle(Lifecycle.State.STARTED) { - launch { + launch("$TAG#viewModel.selectedClockSize") { viewModel.selectedClockSize.collect { val topPadding = when (it) { @@ -55,7 +55,9 @@ object KeyguardPreviewSmartspaceViewBinder { smartspace.setTopPadding(topPadding) } } - launch { viewModel.shouldHideSmartspace.collect { smartspace.isInvisible = it } } + launch("$TAG#viewModel.shouldHideSmartspace") { + viewModel.shouldHideSmartspace.collect { smartspace.isInvisible = it } + } } } } @@ -63,4 +65,6 @@ object KeyguardPreviewSmartspaceViewBinder { private fun View.setTopPadding(padding: Int) { setPaddingRelative(paddingStart, padding, paddingEnd, paddingBottom) } + + private const val TAG = "KeyguardPreviewSmartspaceViewBinder" } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt index abd79ab793d5..6c21e6cdb3bc 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt @@ -30,6 +30,7 @@ import androidx.core.view.isVisible import androidx.core.view.updateLayoutParams import androidx.lifecycle.Lifecycle import androidx.lifecycle.repeatOnLifecycle +import com.android.app.tracing.coroutines.launch import com.android.settingslib.Utils import com.android.systemui.animation.Expandable import com.android.systemui.animation.view.LaunchableImageView @@ -41,11 +42,11 @@ import com.android.systemui.plugins.FalsingManager import com.android.systemui.res.R import com.android.systemui.statusbar.VibratorHelper import com.android.systemui.util.doOnEnd +import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.map -import kotlinx.coroutines.launch /** This is only for a SINGLE Quick affordance */ object KeyguardQuickAffordanceViewBinder { @@ -53,6 +54,7 @@ object KeyguardQuickAffordanceViewBinder { private const val EXIT_DOZE_BUTTON_REVEAL_ANIMATION_DURATION_MS = 250L private const val SCALE_SELECTED_BUTTON = 1.23f private const val DIM_ALPHA = 0.3f + private const val TAG = "KeyguardQuickAffordanceViewBinder" /** * Defines interface for an object that acts as the binding between the view and its view-model. @@ -74,14 +76,15 @@ object KeyguardQuickAffordanceViewBinder { alpha: Flow<Float>, falsingManager: FalsingManager?, vibratorHelper: VibratorHelper?, + mainImmediateDispatcher: CoroutineDispatcher, messageDisplayer: (Int) -> Unit, ): Binding { val button = view as ImageView val configurationBasedDimensions = MutableStateFlow(loadFromResources(view)) val disposableHandle = - view.repeatWhenAttached { + view.repeatWhenAttached(mainImmediateDispatcher) { repeatOnLifecycle(Lifecycle.State.STARTED) { - launch { + launch("$TAG#viewModel.collect") { viewModel.collect { buttonModel -> updateButton( view = button, @@ -93,7 +96,7 @@ object KeyguardQuickAffordanceViewBinder { } } - launch { + launch("$TAG#updateButtonAlpha") { updateButtonAlpha( view = button, viewModel = viewModel, @@ -101,7 +104,7 @@ object KeyguardQuickAffordanceViewBinder { ) } - launch { + launch("$TAG#configurationBasedDimensions") { configurationBasedDimensions.collect { dimensions -> button.updateLayoutParams<ViewGroup.LayoutParams> { width = dimensions.buttonSizePx.width diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt index 33052befadfc..5f50f7ec46e3 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt @@ -33,6 +33,7 @@ import android.view.WindowInsets import androidx.lifecycle.Lifecycle import androidx.lifecycle.repeatOnLifecycle import com.android.app.animation.Interpolators +import com.android.app.tracing.coroutines.launch import com.android.internal.jank.InteractionJankMonitor import com.android.internal.jank.InteractionJankMonitor.CUJ_SCREEN_OFF_SHOW_AOD import com.android.keyguard.KeyguardClockSwitch.MISSING_CLOCK_ID @@ -70,6 +71,7 @@ import com.android.systemui.util.ui.stopAnimating import com.android.systemui.util.ui.value import javax.inject.Provider import kotlin.math.min +import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.DisposableHandle import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.coroutineScope @@ -77,7 +79,6 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.update -import kotlinx.coroutines.launch /** Bind occludingAppDeviceEntryMessageViewModel to run whenever the keyguard view is attached. */ @OptIn(ExperimentalCoroutinesApi::class) @@ -98,6 +99,7 @@ object KeyguardRootViewBinder { vibratorHelper: VibratorHelper?, falsingManager: FalsingManager?, keyguardViewMediator: KeyguardViewMediator?, + mainImmediateDispatcher: CoroutineDispatcher, ): DisposableHandle { var onLayoutChangeListener: OnLayoutChange? = null val childViews = mutableMapOf<Int, View>() @@ -118,9 +120,9 @@ object KeyguardRootViewBinder { ) val disposableHandle = - view.repeatWhenAttached { + view.repeatWhenAttached(mainImmediateDispatcher) { repeatOnLifecycle(Lifecycle.State.CREATED) { - launch { + launch("$TAG#occludingAppDeviceEntryMessageViewModel.message") { occludingAppDeviceEntryMessageViewModel.message.collect { biometricMessage -> if (biometricMessage?.message != null) { @@ -139,7 +141,7 @@ object KeyguardRootViewBinder { if ( KeyguardBottomAreaRefactor.isEnabled || DeviceEntryUdfpsRefactor.isEnabled ) { - launch { + launch("$TAG#viewModel.alpha") { viewModel.alpha(viewState).collect { alpha -> view.alpha = alpha if (KeyguardBottomAreaRefactor.isEnabled) { @@ -151,21 +153,21 @@ object KeyguardRootViewBinder { } if (MigrateClocksToBlueprint.isEnabled) { - launch { + launch("$TAG#viewModel.burnInLayerVisibility") { viewModel.burnInLayerVisibility.collect { visibility -> childViews[burnInLayerId]?.visibility = visibility childViews[aodNotificationIconContainerId]?.visibility = visibility } } - launch { + launch("$TAG#viewModel.burnInLayerAlpha") { viewModel.burnInLayerAlpha.collect { alpha -> childViews[statusViewId]?.alpha = alpha childViews[aodNotificationIconContainerId]?.alpha = alpha } } - launch { + launch("$TAG#viewModel.topClippingBounds") { val clipBounds = Rect() viewModel.topClippingBounds.collect { clipTop -> if (clipTop == null) { @@ -182,13 +184,13 @@ object KeyguardRootViewBinder { } } - launch { + launch("$TAG#viewModel.lockscreenStateAlpha") { viewModel.lockscreenStateAlpha(viewState).collect { alpha -> childViews[statusViewId]?.alpha = alpha } } - launch { + launch("$TAG#viewModel.translationY") { // When translation happens in burnInLayer, it won't be weather clock // large clock isn't added to burnInLayer due to its scale transition // so we also need to add translation to it here @@ -200,7 +202,7 @@ object KeyguardRootViewBinder { } } - launch { + launch("$TAG#viewModel.translationX") { viewModel.translationX.collect { state -> val px = state.value ?: return@collect when { @@ -227,7 +229,7 @@ object KeyguardRootViewBinder { } } - launch { + launch("$TAG#viewModel.scale") { viewModel.scale.collect { scaleViewModel -> if (scaleViewModel.scaleClockOnly) { // For clocks except weather clock, we have scale transition @@ -258,7 +260,7 @@ object KeyguardRootViewBinder { } if (NotificationIconContainerRefactor.isEnabled) { - launch { + launch("$TAG#viewModel.isNotifIconContainerVisible") { val iconsAppearTranslationPx = configuration .getDimensionPixelSize(R.dimen.shelf_appear_translation) @@ -275,7 +277,7 @@ object KeyguardRootViewBinder { } interactionJankMonitor?.let { jankMonitor -> - launch { + launch("$TAG#viewModel.goneToAodTransition") { viewModel.goneToAodTransition.collect { when (it.transitionState) { TransitionState.STARTED -> { @@ -304,7 +306,7 @@ object KeyguardRootViewBinder { } } - launch { + launch("$TAG#shadeInteractor.isAnyFullyExpanded") { shadeInteractor.isAnyFullyExpanded.collect { isFullyAnyExpanded -> view.visibility = if (isFullyAnyExpanded) { @@ -315,10 +317,12 @@ object KeyguardRootViewBinder { } } - launch { burnInParams.collect { viewModel.updateBurnInParams(it) } } + launch("$TAG#burnInParams.collect") { + burnInParams.collect { viewModel.updateBurnInParams(it) } + } if (deviceEntryHapticsInteractor != null && vibratorHelper != null) { - launch { + launch("$TAG#deviceEntryHapticsInteractor.playSuccessHaptic") { deviceEntryHapticsInteractor.playSuccessHaptic.collect { vibratorHelper.performHapticFeedback( view, @@ -328,7 +332,7 @@ object KeyguardRootViewBinder { } } - launch { + launch("$TAG#deviceEntryHapticsInteractor.playErrorHaptic") { deviceEntryHapticsInteractor.playErrorHaptic.collect { vibratorHelper.performHapticFeedback( view, @@ -593,4 +597,5 @@ object KeyguardRootViewBinder { private const val ID = "occluding_app_device_entry_unlock_msg" private const val AOD_ICONS_APPEAR_DURATION: Long = 200 + private const val TAG = "KeyguardRootViewBinder" } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardSettingsViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardSettingsViewBinder.kt index b1adef46e782..fa5756522a6a 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardSettingsViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardSettingsViewBinder.kt @@ -22,6 +22,7 @@ import android.view.View import androidx.core.view.isVisible import androidx.lifecycle.Lifecycle import androidx.lifecycle.repeatOnLifecycle +import com.android.app.tracing.coroutines.launch import com.android.systemui.animation.ActivityTransitionAnimator import com.android.systemui.common.ui.binder.IconViewBinder import com.android.systemui.common.ui.binder.TextViewBinder @@ -38,7 +39,6 @@ import kotlinx.coroutines.DisposableHandle import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.filterNotNull -import kotlinx.coroutines.launch object KeyguardSettingsViewBinder { fun bind( @@ -52,7 +52,7 @@ object KeyguardSettingsViewBinder { val disposableHandle = view.repeatWhenAttached { repeatOnLifecycle(Lifecycle.State.STARTED) { - launch { + launch("$TAG#viewModel.isVisible") { viewModel.isVisible.distinctUntilChanged().collect { isVisible -> view.animateVisibility(visible = isVisible) if (isVisible) { @@ -78,7 +78,7 @@ object KeyguardSettingsViewBinder { // shows up in the Wallpaper Picker app. If we do that, then the // settings menu should never be visible. if (activityStarter != null) { - launch { + launch("$TAG#viewModel.shouldOpenSettings") { viewModel.shouldOpenSettings .filter { it } .collect { @@ -91,7 +91,7 @@ object KeyguardSettingsViewBinder { } } - launch { + launch("$TAG#rootViewModel?.lastRootViewTapPosition") { rootViewModel?.lastRootViewTapPosition?.filterNotNull()?.collect { point -> if (view.isVisible) { val hitRect = Rect() @@ -136,4 +136,6 @@ object KeyguardSettingsViewBinder { } .start() } + + private const val TAG = "KeyguardSettingsViewBinder" } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardSmartspaceViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardSmartspaceViewBinder.kt index 9aebf66aa067..6b11dc57e096 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardSmartspaceViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardSmartspaceViewBinder.kt @@ -21,6 +21,7 @@ import androidx.constraintlayout.helper.widget.Layer import androidx.constraintlayout.widget.ConstraintLayout import androidx.lifecycle.Lifecycle import androidx.lifecycle.repeatOnLifecycle +import com.android.app.tracing.coroutines.launch import com.android.systemui.keyguard.MigrateClocksToBlueprint import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor import com.android.systemui.keyguard.ui.view.layout.blueprints.transitions.IntraBlueprintTransition.Config @@ -30,7 +31,6 @@ import com.android.systemui.keyguard.ui.viewmodel.KeyguardSmartspaceViewModel import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.res.R import com.android.systemui.shared.R as sharedR -import kotlinx.coroutines.launch object KeyguardSmartspaceViewBinder { @JvmStatic @@ -42,7 +42,7 @@ object KeyguardSmartspaceViewBinder { ) { keyguardRootView.repeatWhenAttached { repeatOnLifecycle(Lifecycle.State.CREATED) { - launch { + launch("$TAG#clockViewModel.hasCustomWeatherDataDisplay") { if (!MigrateClocksToBlueprint.isEnabled) return@launch clockViewModel.hasCustomWeatherDataDisplay.collect { hasCustomWeatherDataDisplay -> @@ -61,7 +61,7 @@ object KeyguardSmartspaceViewBinder { } } - launch { + launch("$TAG#smartspaceViewModel.bcSmartspaceVisibility") { if (!MigrateClocksToBlueprint.isEnabled) return@launch smartspaceViewModel.bcSmartspaceVisibility.collect { updateBCSmartspaceInBurnInLayer(keyguardRootView, clockViewModel) @@ -148,4 +148,6 @@ object KeyguardSmartspaceViewBinder { } } } + + private const val TAG = "KeyguardSmartspaceViewBinder" } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardSurfaceBehindViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardSurfaceBehindViewBinder.kt index 599f69f4bc38..fd27dc39299b 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardSurfaceBehindViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardSurfaceBehindViewBinder.kt @@ -16,10 +16,10 @@ package com.android.systemui.keyguard.ui.binder +import com.android.app.tracing.coroutines.launch import com.android.systemui.keyguard.WindowManagerLockscreenVisibilityManager import com.android.systemui.keyguard.ui.viewmodel.KeyguardSurfaceBehindViewModel import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.launch /** * Binds the [WindowManagerLockscreenVisibilityManager] "view", which manages the visibility of the @@ -32,6 +32,10 @@ object KeyguardSurfaceBehindViewBinder { applier: KeyguardSurfaceBehindParamsApplier, scope: CoroutineScope ) { - scope.launch { viewModel.surfaceBehindViewParams.collect { applier.viewParams = it } } + scope.launch("$TAG#viewModel.surfaceBehindViewParams") { + viewModel.surfaceBehindViewParams.collect { applier.viewParams = it } + } } + + private const val TAG = "KeyguardSurfaceBehindViewBinder" } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/LightRevealScrimViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/LightRevealScrimViewBinder.kt index f1da8826a22c..b2ee68967878 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/LightRevealScrimViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/LightRevealScrimViewBinder.kt @@ -18,6 +18,7 @@ package com.android.systemui.keyguard.ui.binder import androidx.lifecycle.Lifecycle import androidx.lifecycle.repeatOnLifecycle +import com.android.app.tracing.coroutines.launch import com.android.systemui.keyguard.ui.viewmodel.LightRevealScrimViewModel import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.statusbar.LightRevealScrim @@ -28,11 +29,11 @@ object LightRevealScrimViewBinder { fun bind(revealScrim: LightRevealScrim, viewModel: LightRevealScrimViewModel) { revealScrim.repeatWhenAttached { repeatOnLifecycle(Lifecycle.State.CREATED) { - launch { + launch("$TAG#viewModel.revealAmount") { viewModel.revealAmount.collect { amount -> revealScrim.revealAmount = amount } } - launch { + launch("$TAG#viewModel.lightRevealEffect") { viewModel.lightRevealEffect.collect { effect -> revealScrim.revealEffect = effect } @@ -40,4 +41,6 @@ object LightRevealScrimViewBinder { } } } + + private const val TAG = "LightRevealScrimViewBinder" } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/WindowManagerLockscreenVisibilityViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/WindowManagerLockscreenVisibilityViewBinder.kt index fc0c78a6f76b..ae46dd3a6ef3 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/WindowManagerLockscreenVisibilityViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/WindowManagerLockscreenVisibilityViewBinder.kt @@ -16,39 +16,41 @@ package com.android.systemui.keyguard.ui.binder +import com.android.app.tracing.coroutines.launch import com.android.systemui.keyguard.WindowManagerLockscreenVisibilityManager import com.android.systemui.keyguard.ui.viewmodel.WindowManagerLockscreenVisibilityViewModel import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.launch /** * Binds the [WindowManagerLockscreenVisibilityManager] "view", which manages the visibility of the * surface behind the keyguard. */ object WindowManagerLockscreenVisibilityViewBinder { + private const val TAG = "WindowManagerLockscreenVisibilityViewBinder" + @JvmStatic fun bind( viewModel: WindowManagerLockscreenVisibilityViewModel, lockscreenVisibilityManager: WindowManagerLockscreenVisibilityManager, scope: CoroutineScope ) { - scope.launch { + scope.launch("$TAG#viewModel.surfaceBehindVisibility") { viewModel.surfaceBehindVisibility.collect { lockscreenVisibilityManager.setSurfaceBehindVisibility(it) } } - scope.launch { + scope.launch("$TAG#viewModel.lockscreenVisibility") { viewModel.lockscreenVisibility.collect { lockscreenVisibilityManager.setLockscreenShown(it) } } - scope.launch { + scope.launch("$TAG#viewModel.aodVisibility") { viewModel.aodVisibility.collect { lockscreenVisibilityManager.setAodVisible(it) } } - scope.launch { + scope.launch("$TAG#viewModel.surfaceBehindAnimating") { viewModel.surfaceBehindAnimating.collect { lockscreenVisibilityManager.setUsingGoingAwayRemoteAnimation(it) } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt index 1c33579b15c7..9195b4f4e7fc 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt @@ -383,6 +383,7 @@ constructor( null, // device entry haptics not required for preview mode null, // falsing manager not required for preview mode null, // keyguard view mediator is not required for preview mode + mainDispatcher, ) } rootView.addView( @@ -449,6 +450,7 @@ constructor( alpha = flowOf(1f), falsingManager = falsingManager, vibratorHelper = vibratorHelper, + mainImmediateDispatcher = mainDispatcher, ) { message -> indicationController.showTransientIndication(message) } @@ -463,6 +465,7 @@ constructor( alpha = flowOf(1f), falsingManager = falsingManager, vibratorHelper = vibratorHelper, + mainImmediateDispatcher = mainDispatcher, ) { message -> indicationController.showTransientIndication(message) } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AlignShortcutsToUdfpsSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AlignShortcutsToUdfpsSection.kt index 2e9663897f89..5404729d1819 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AlignShortcutsToUdfpsSection.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AlignShortcutsToUdfpsSection.kt @@ -36,6 +36,7 @@ import com.android.systemui.res.R import com.android.systemui.statusbar.KeyguardIndicationController import com.android.systemui.statusbar.VibratorHelper import javax.inject.Inject +import kotlinx.coroutines.CoroutineDispatcher class AlignShortcutsToUdfpsSection @Inject @@ -47,6 +48,7 @@ constructor( private val falsingManager: FalsingManager, private val indicationController: KeyguardIndicationController, private val vibratorHelper: VibratorHelper, + @Main private val mainImmediateDispatcher: CoroutineDispatcher, ) : BaseShortcutSection() { override fun addViews(constraintLayout: ConstraintLayout) { if (KeyguardBottomAreaRefactor.isEnabled) { @@ -64,6 +66,7 @@ constructor( keyguardQuickAffordancesCombinedViewModel.transitionAlpha, falsingManager, vibratorHelper, + mainImmediateDispatcher, ) { indicationController.showTransientIndication(it) } @@ -74,6 +77,7 @@ constructor( keyguardQuickAffordancesCombinedViewModel.transitionAlpha, falsingManager, vibratorHelper, + mainImmediateDispatcher, ) { indicationController.showTransientIndication(it) } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSection.kt index 78a1fcfe4258..e0bf8152d11f 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSection.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSection.kt @@ -45,6 +45,7 @@ import com.android.systemui.res.R import com.android.systemui.shared.R as sharedR import dagger.Lazy import javax.inject.Inject +import kotlinx.coroutines.DisposableHandle internal fun ConstraintSet.setVisibility( views: Iterable<View>, @@ -65,19 +66,23 @@ constructor( val smartspaceViewModel: KeyguardSmartspaceViewModel, val blueprintInteractor: Lazy<KeyguardBlueprintInteractor>, ) : KeyguardSection() { + private var handle: DisposableHandle? = null + override fun addViews(constraintLayout: ConstraintLayout) {} override fun bindData(constraintLayout: ConstraintLayout) { if (!MigrateClocksToBlueprint.isEnabled) { return } - KeyguardClockViewBinder.bind( - this, - constraintLayout, - keyguardClockViewModel, - clockInteractor, - blueprintInteractor.get() - ) + handle?.dispose() + handle = + KeyguardClockViewBinder.bind( + this, + constraintLayout, + keyguardClockViewModel, + clockInteractor, + blueprintInteractor.get() + ) } override fun applyConstraints(constraintSet: ConstraintSet) { @@ -89,7 +94,13 @@ constructor( } } - override fun removeViews(constraintLayout: ConstraintLayout) {} + override fun removeViews(constraintLayout: ConstraintLayout) { + if (!MigrateClocksToBlueprint.isEnabled) { + return + } + handle?.dispose() + handle = null + } private fun buildConstraints( clock: ClockController, diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySection.kt index 29041d1665c3..865e989c5b68 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySection.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySection.kt @@ -30,6 +30,7 @@ import com.android.keyguard.LockIconView import com.android.keyguard.LockIconViewController import com.android.systemui.biometrics.AuthController import com.android.systemui.dagger.qualifiers.Application +import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor import com.android.systemui.flags.FeatureFlags import com.android.systemui.flags.Flags @@ -47,6 +48,7 @@ import com.android.systemui.shade.NotificationPanelView import com.android.systemui.statusbar.VibratorHelper import dagger.Lazy import javax.inject.Inject +import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -67,6 +69,7 @@ constructor( private val deviceEntryBackgroundViewModel: Lazy<DeviceEntryBackgroundViewModel>, private val falsingManager: Lazy<FalsingManager>, private val vibratorHelper: Lazy<VibratorHelper>, + @Main private val mainImmediateDispatcher: CoroutineDispatcher, ) : KeyguardSection() { private val deviceEntryIconViewId = R.id.device_entry_icon_view @@ -104,6 +107,7 @@ constructor( deviceEntryBackgroundViewModel.get(), falsingManager.get(), vibratorHelper.get(), + mainImmediateDispatcher, ) } } else { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultShortcutsSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultShortcutsSection.kt index 45b82576c6c4..27ca5cdbad17 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultShortcutsSection.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultShortcutsSection.kt @@ -35,6 +35,7 @@ import com.android.systemui.res.R import com.android.systemui.statusbar.KeyguardIndicationController import com.android.systemui.statusbar.VibratorHelper import javax.inject.Inject +import kotlinx.coroutines.CoroutineDispatcher class DefaultShortcutsSection @Inject @@ -46,6 +47,7 @@ constructor( private val falsingManager: FalsingManager, private val indicationController: KeyguardIndicationController, private val vibratorHelper: VibratorHelper, + @Main private val mainImmediateDispatcher: CoroutineDispatcher, ) : BaseShortcutSection() { override fun addViews(constraintLayout: ConstraintLayout) { if (KeyguardBottomAreaRefactor.isEnabled) { @@ -63,6 +65,7 @@ constructor( keyguardQuickAffordancesCombinedViewModel.transitionAlpha, falsingManager, vibratorHelper, + mainImmediateDispatcher, ) { indicationController.showTransientIndication(it) } @@ -73,6 +76,7 @@ constructor( keyguardQuickAffordancesCombinedViewModel.transitionAlpha, falsingManager, vibratorHelper, + mainImmediateDispatcher, ) { indicationController.showTransientIndication(it) } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt index e8313a9f739c..64e15659d08b 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt @@ -20,6 +20,7 @@ package com.android.systemui.keyguard.ui.viewmodel import android.graphics.Point import android.util.MathUtils import android.view.View.VISIBLE +import com.android.app.tracing.coroutines.launch import com.android.systemui.Flags.newAodTransition import com.android.systemui.common.shared.model.NotificationContainerBounds import com.android.systemui.communal.domain.interactor.CommunalInteractor @@ -268,7 +269,9 @@ constructor( burnInJob?.cancel() burnInJob = - scope.launch { aodBurnInViewModel.movement(params).collect { burnInModel.value = it } } + scope.launch("$TAG#aodBurnInViewModel") { + aodBurnInViewModel.movement(params).collect { burnInModel.value = it } + } } val scale: Flow<BurnInScaleViewModel> = @@ -368,4 +371,8 @@ constructor( fun setRootViewLastTapPosition(point: Point) { keyguardInteractor.setLastRootViewTapPosition(point) } + + companion object { + private const val TAG = "KeyguardRootViewModel" + } } diff --git a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt index 3d0d8fb4abe4..6a35340dec58 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt @@ -142,6 +142,7 @@ class ClockEventControllerTest : SysuiTestCase() { context.resources, context, mainExecutor, + IMMEDIATE, bgExecutor, clockBuffers, withDeps.featureFlags, diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeUiTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeUiTest.java index 7311f4a5ef71..e7caf000ef67 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeUiTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeUiTest.java @@ -41,6 +41,8 @@ import androidx.test.runner.AndroidJUnit4; import com.android.systemui.DejankUtils; import com.android.systemui.SysuiTestCase; import com.android.systemui.statusbar.phone.DozeParameters; +import com.android.systemui.util.concurrency.FakeExecutor; +import com.android.systemui.util.time.FakeSystemClock; import com.android.systemui.util.wakelock.WakeLockFake; import org.junit.After; @@ -69,6 +71,7 @@ public class DozeUiTest extends SysuiTestCase { private Handler mHandler; private HandlerThread mHandlerThread; private DozeUi mDozeUi; + private FakeExecutor mFakeExecutor; @Before public void setUp() throws Exception { @@ -80,9 +83,9 @@ public class DozeUiTest extends SysuiTestCase { mHandlerThread.start(); mWakeLock = new WakeLockFake(); mHandler = mHandlerThread.getThreadHandler(); - + mFakeExecutor = new FakeExecutor(new FakeSystemClock()); mDozeUi = new DozeUi(mContext, mAlarmManager, mWakeLock, mHost, mHandler, - mDozeParameters, mDozeLog); + mDozeParameters, mFakeExecutor, mDozeLog); mDozeUi.setDozeMachine(mMachine); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySectionTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySectionTest.kt index 4f2b690f9fcd..b5f668cef08c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySectionTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySectionTest.kt @@ -38,6 +38,7 @@ import com.android.systemui.shade.NotificationPanelView import com.android.systemui.statusbar.VibratorHelper import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.test.TestScope @@ -85,6 +86,7 @@ class DefaultDeviceEntrySectionTest : SysuiTestCase() { { mock(DeviceEntryBackgroundViewModel::class.java) }, { falsingManager }, { mock(VibratorHelper::class.java) }, + mock(CoroutineDispatcher::class.java), ) } |