summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/AlternateBouncer.kt23
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinder.kt29
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/view/AlternateBouncerWindowViewBinder.kt102
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/view/AlternateBouncerWindowViewLayoutParams.kt46
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootView.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt33
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/ShadeViewProviderModule.kt3
8 files changed, 182 insertions, 64 deletions
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/AlternateBouncer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/AlternateBouncer.kt
index 1475795e2dc6..d02215083679 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/AlternateBouncer.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/AlternateBouncer.kt
@@ -18,6 +18,7 @@ package com.android.systemui.keyguard.ui.composable
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.Crossfade
+import androidx.compose.animation.core.MutableTransitionState
import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
@@ -29,7 +30,9 @@ import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
+import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
@@ -60,13 +63,25 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi
@Composable
fun AlternateBouncer(
alternateBouncerDependencies: AlternateBouncerDependencies,
+ onHideAnimationFinished: () -> Unit,
modifier: Modifier = Modifier,
) {
val isVisible by
- alternateBouncerDependencies.viewModel.isVisible.collectAsStateWithLifecycle(
- initialValue = false
- )
+ alternateBouncerDependencies.viewModel.isVisible.collectAsStateWithLifecycle(true)
+ val visibleState = remember { MutableTransitionState(isVisible) }
+
+ // Feeds the isVisible value to the MutableTransitionState used by AnimatedVisibility below.
+ LaunchedEffect(isVisible) { visibleState.targetState = isVisible }
+
+ // Watches the MutableTransitionState and calls onHideAnimationFinished when the fade out
+ // animation is finished. This way the window view is removed from the view hierarchy only after
+ // the fade out animation is complete.
+ LaunchedEffect(visibleState.currentState, visibleState.isIdle) {
+ if (!visibleState.currentState && visibleState.isIdle) {
+ onHideAnimationFinished()
+ }
+ }
val udfpsIconLocation by
alternateBouncerDependencies.udfpsIconViewModel.iconLocation.collectAsStateWithLifecycle(
@@ -74,7 +89,7 @@ fun AlternateBouncer(
)
AnimatedVisibility(
- visible = isVisible,
+ visibleState = visibleState,
enter = fadeIn(),
exit = fadeOut(),
modifier = modifier,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
index 0101e099084e..096439b1008d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
@@ -62,6 +62,7 @@ import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionBootInteractor;
import com.android.systemui.keyguard.domain.interactor.StartKeyguardTransitionModule;
import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransitionModule;
+import com.android.systemui.keyguard.ui.view.AlternateBouncerWindowViewBinder;
import com.android.systemui.keyguard.ui.viewmodel.KeyguardQuickAffordancesCombinedViewModelModule;
import com.android.systemui.log.SessionTracker;
import com.android.systemui.navigationbar.NavigationModeController;
@@ -248,4 +249,10 @@ public interface KeyguardModule {
@IntoMap
@ClassKey(KeyguardUpdateMonitor.class)
CoreStartable bindsKeyguardUpdateMonitor(KeyguardUpdateMonitor keyguardUpdateMonitor);
+
+ /***/
+ @Binds
+ @IntoMap
+ @ClassKey(AlternateBouncerWindowViewBinder.class)
+ CoreStartable bindsAlternateBouncerWindowViewBinder(AlternateBouncerWindowViewBinder binder);
}
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 7a368999ecc9..33783b515763 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
@@ -16,9 +16,7 @@
package com.android.systemui.keyguard.ui.binder
-import android.graphics.PixelFormat
import android.util.Log
-import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@@ -36,6 +34,7 @@ import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.deviceentry.ui.binder.UdfpsAccessibilityOverlayBinder
import com.android.systemui.deviceentry.ui.view.UdfpsAccessibilityOverlay
import com.android.systemui.deviceentry.ui.viewmodel.AlternateBouncerUdfpsAccessibilityOverlayViewModel
+import com.android.systemui.keyguard.ui.view.AlternateBouncerWindowViewLayoutParams
import com.android.systemui.keyguard.ui.view.DeviceEntryIconView
import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerDependencies
import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerUdfpsIconViewModel
@@ -68,28 +67,6 @@ constructor(
private val windowManager: Lazy<WindowManager>,
private val layoutInflater: Lazy<LayoutInflater>,
) : CoreStartable {
- private val layoutParams: WindowManager.LayoutParams
- get() =
- WindowManager.LayoutParams(
- WindowManager.LayoutParams.MATCH_PARENT,
- WindowManager.LayoutParams.MATCH_PARENT,
- WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG,
- WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN or
- WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
- PixelFormat.TRANSLUCENT,
- )
- .apply {
- title = "AlternateBouncerView"
- fitInsetsTypes = 0 // overrides default, avoiding status bars during layout
- gravity = Gravity.TOP or Gravity.LEFT
- layoutInDisplayCutoutMode =
- WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
- privateFlags =
- WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY or
- WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION
- // Avoid announcing window title.
- accessibilityTitle = " "
- }
private var alternateBouncerView: ConstraintLayout? = null
@@ -176,7 +153,9 @@ constructor(
as ConstraintLayout
Log.d(TAG, "Adding alternate bouncer view")
- windowManager.get().addView(alternateBouncerView, layoutParams)
+ windowManager
+ .get()
+ .addView(alternateBouncerView, AlternateBouncerWindowViewLayoutParams.layoutParams)
alternateBouncerView!!.addOnAttachStateChangeListener(onAttachAddBackGestureHandler)
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/AlternateBouncerWindowViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/AlternateBouncerWindowViewBinder.kt
new file mode 100644
index 000000000000..d3bc79eb89e2
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/AlternateBouncerWindowViewBinder.kt
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyguard.ui.view
+
+import android.content.Context
+import android.view.View
+import android.view.WindowManager
+import android.widget.FrameLayout
+import androidx.compose.ui.platform.ComposeView
+import com.android.systemui.CoreStartable
+import com.android.systemui.compose.ComposeInitializer
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.keyguard.ui.composable.AlternateBouncer
+import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerDependencies
+import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerViewModel
+import com.android.systemui.lifecycle.repeatWhenAttached
+import com.android.systemui.lifecycle.repeatWhenAttachedToWindow
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.awaitCancellation
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.filter
+import kotlinx.coroutines.launch
+
+/** Drives the showing and hiding of the alternate bouncer window. */
+@SysUISingleton
+class AlternateBouncerWindowViewBinder
+@Inject
+constructor(
+ @Application private val applicationScope: CoroutineScope,
+ @Application private val context: Context,
+ private val viewModel: AlternateBouncerViewModel,
+ private val dependencies: AlternateBouncerDependencies,
+ private val windowManager: WindowManager,
+) : CoreStartable {
+
+ override fun start() {
+ if (!SceneContainerFlag.isEnabled) {
+ return
+ }
+
+ applicationScope.launch {
+ viewModel.isVisible
+ .distinctUntilChanged()
+ .filter { it }
+ .collect {
+ windowManager.addView(
+ createView(),
+ AlternateBouncerWindowViewLayoutParams.layoutParams,
+ )
+ }
+ }
+ }
+
+ private fun createView(): View {
+ val root = FrameLayout(context)
+ val composeView =
+ ComposeView(context).apply {
+ setContent {
+ AlternateBouncer(
+ alternateBouncerDependencies = dependencies,
+ onHideAnimationFinished = {
+ if (root.isAttachedToWindow) {
+ windowManager.removeView(root)
+ }
+ },
+ )
+ }
+ }
+
+ root.repeatWhenAttached {
+ root.repeatWhenAttachedToWindow {
+ try {
+ ComposeInitializer.onAttachedToWindow(root)
+ root.addView(composeView)
+ awaitCancellation()
+ } finally {
+ root.removeView(composeView)
+ ComposeInitializer.onDetachedFromWindow(root)
+ }
+ }
+ }
+
+ return root
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/AlternateBouncerWindowViewLayoutParams.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/AlternateBouncerWindowViewLayoutParams.kt
new file mode 100644
index 000000000000..5585c21aa217
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/AlternateBouncerWindowViewLayoutParams.kt
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyguard.ui.view
+
+import android.graphics.PixelFormat
+import android.view.Gravity
+import android.view.WindowManager
+
+object AlternateBouncerWindowViewLayoutParams {
+ val layoutParams: WindowManager.LayoutParams
+ get() =
+ WindowManager.LayoutParams(
+ WindowManager.LayoutParams.MATCH_PARENT,
+ WindowManager.LayoutParams.MATCH_PARENT,
+ WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG,
+ WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN or
+ WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
+ PixelFormat.TRANSLUCENT,
+ )
+ .apply {
+ title = "AlternateBouncerView"
+ fitInsetsTypes = 0 // overrides default, avoiding status bars during layout
+ gravity = Gravity.TOP or Gravity.LEFT
+ layoutInDisplayCutoutMode =
+ WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
+ privateFlags =
+ WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY or
+ WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION
+ // Avoid announcing window title.
+ accessibilityTitle = " "
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootView.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootView.kt
index 7d7cab41cf96..c45906840385 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootView.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootView.kt
@@ -5,7 +5,6 @@ import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import android.view.WindowInsets
-import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerDependencies
import com.android.systemui.qs.ui.adapter.QSSceneAdapter
import com.android.systemui.scene.shared.model.SceneContainerConfig
import com.android.systemui.scene.shared.model.SceneDataSourceDelegator
@@ -35,7 +34,6 @@ class SceneWindowRootView(context: Context, attrs: AttributeSet?) : WindowRootVi
layoutInsetController: LayoutInsetsController,
sceneDataSourceDelegator: SceneDataSourceDelegator,
qsSceneAdapter: Provider<QSSceneAdapter>,
- alternateBouncerDependencies: AlternateBouncerDependencies,
) {
setLayoutInsetsController(layoutInsetController)
SceneWindowRootViewBinder.bind(
@@ -54,7 +52,6 @@ class SceneWindowRootView(context: Context, attrs: AttributeSet?) : WindowRootVi
},
dataSourceDelegator = sceneDataSourceDelegator,
qsSceneAdapter = qsSceneAdapter,
- alternateBouncerDependencies = alternateBouncerDependencies,
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt
index 1c15c74d5631..f7061d9af961 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt
@@ -36,15 +36,12 @@ import com.android.internal.policy.ScreenDecorationsUtils
import com.android.systemui.common.ui.compose.windowinsets.CutoutLocation
import com.android.systemui.common.ui.compose.windowinsets.DisplayCutout
import com.android.systemui.common.ui.compose.windowinsets.ScreenDecorProvider
-import com.android.systemui.keyguard.ui.composable.AlternateBouncer
-import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerDependencies
import com.android.systemui.lifecycle.WindowLifecycleState
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.lifecycle.setSnapshotBinding
import com.android.systemui.lifecycle.viewModel
import com.android.systemui.qs.ui.adapter.QSSceneAdapter
import com.android.systemui.res.R
-import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.scene.shared.model.SceneContainerConfig
import com.android.systemui.scene.shared.model.SceneDataSourceDelegator
import com.android.systemui.scene.ui.composable.Overlay
@@ -77,7 +74,6 @@ object SceneWindowRootViewBinder {
onVisibilityChangedInternal: (isVisible: Boolean) -> Unit,
dataSourceDelegator: SceneDataSourceDelegator,
qsSceneAdapter: Provider<QSSceneAdapter>,
- alternateBouncerDependencies: AlternateBouncerDependencies,
) {
val unsortedSceneByKey: Map<SceneKey, Scene> = scenes.associateBy { scene -> scene.key }
val sortedSceneByKey: Map<SceneKey, Scene> =
@@ -148,20 +144,10 @@ object SceneWindowRootViewBinder {
// the SceneContainerView. This SharedNotificationContainer should contain NSSL
// due to the NotificationStackScrollLayoutSection (legacy) or
// NotificationSection (scene container) moving it there.
- if (SceneContainerFlag.isEnabled) {
- (sharedNotificationContainer.parent as? ViewGroup)?.removeView(
- sharedNotificationContainer
- )
- view.addView(sharedNotificationContainer)
-
- // TODO(b/358354906): use an overlay for the alternate bouncer
- view.addView(
- createAlternateBouncerView(
- context = view.context,
- alternateBouncerDependencies = alternateBouncerDependencies,
- )
- )
- }
+ (sharedNotificationContainer.parent as? ViewGroup)?.removeView(
+ sharedNotificationContainer
+ )
+ view.addView(sharedNotificationContainer)
view.setSnapshotBinding { onVisibilityChangedInternal(viewModel.isVisible) }
awaitCancellation()
@@ -206,17 +192,6 @@ object SceneWindowRootViewBinder {
}
}
- private fun createAlternateBouncerView(
- context: Context,
- alternateBouncerDependencies: AlternateBouncerDependencies,
- ): ComposeView {
- return ComposeView(context).apply {
- setContent {
- AlternateBouncer(alternateBouncerDependencies = alternateBouncerDependencies)
- }
- }
- }
-
// TODO(b/298525212): remove once Compose exposes window inset bounds.
private fun displayCutoutFromWindowInsets(
scope: CoroutineScope,
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeViewProviderModule.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeViewProviderModule.kt
index 15b22700072f..8937ce33cd38 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeViewProviderModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeViewProviderModule.kt
@@ -33,7 +33,6 @@ import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.keyguard.ui.view.KeyguardRootView
-import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerDependencies
import com.android.systemui.privacy.OngoingPrivacyChip
import com.android.systemui.qs.ui.adapter.QSSceneAdapter
import com.android.systemui.res.R
@@ -91,7 +90,6 @@ abstract class ShadeViewProviderModule {
layoutInsetController: NotificationInsetsController,
sceneDataSourceDelegator: Provider<SceneDataSourceDelegator>,
qsSceneAdapter: Provider<QSSceneAdapter>,
- alternateBouncerDependencies: Provider<AlternateBouncerDependencies>,
): WindowRootView {
return if (SceneContainerFlag.isEnabled) {
checkNoSceneDuplicates(scenesProvider.get())
@@ -107,7 +105,6 @@ abstract class ShadeViewProviderModule {
layoutInsetController = layoutInsetController,
sceneDataSourceDelegator = sceneDataSourceDelegator.get(),
qsSceneAdapter = qsSceneAdapter,
- alternateBouncerDependencies = alternateBouncerDependencies.get(),
)
sceneWindowRootView
} else {