summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Jordan Demeulenaere <jdemeulenaere@google.com> 2024-02-28 16:17:50 +0100
committer Jordan Demeulenaere <jdemeulenaere@google.com> 2024-03-01 14:59:36 +0100
commite8c26a68f55a36c7cbecc42fff1b3a5f7648661f (patch)
treef54edbeb8bddf63d8592fe1085adcf5d23b32231
parent016b4dae2fdddcf8604bb6979c6540e99cf22b19 (diff)
Remove (Base)ComposeFacade
Bug: 295304993 Test: mp sysuig Flag: N/A Change-Id: I4f70577387ae3e76a807d7c4ee4b04eca481a5a0
-rw-r--r--packages/SystemUI/compose/facade/enabled/src/com/android/systemui/compose/ComposeFacade.kt250
-rw-r--r--packages/SystemUI/compose/facade/enabled/src/com/android/systemui/compose/ComposeInitializerImpl.kt77
-rw-r--r--packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/BouncerViewBinder.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/ComposeBouncerViewBinder.kt13
-rw-r--r--packages/SystemUI/src/com/android/systemui/communal/widgets/EditWidgetsActivity.kt113
-rw-r--r--packages/SystemUI/src/com/android/systemui/compose/BaseComposeFacade.kt130
-rw-r--r--packages/SystemUI/src/com/android/systemui/compose/ComposeInitializer.kt58
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/stickykeys/ui/StickyKeyDialogFactory.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/stickykeys/ui/StickyKeysIndicatorCoordinator.kt9
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt23
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/shared/ComposeLockscreen.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.kt15
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSImpl.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSUtils.kt19
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlags.kt12
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt89
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/ui/view/WindowRootView.kt10
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt15
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/panel/shared/flag/VolumePanelFlag.kt9
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/panel/ui/activity/VolumePanelActivity.kt5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/compose/ComposeInitializerTest.kt8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyboard/stickykeys/ui/StickyKeysIndicatorCoordinatorTest.kt15
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/GlanceableHubContainerControllerTest.kt11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt11
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/flags/SceneContainerRule.kt5
25 files changed, 301 insertions, 616 deletions
diff --git a/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/compose/ComposeFacade.kt b/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/compose/ComposeFacade.kt
deleted file mode 100644
index 76931a2b4d41..000000000000
--- a/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/compose/ComposeFacade.kt
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.compose
-
-import android.content.Context
-import android.graphics.Point
-import android.view.View
-import android.view.WindowInsets
-import androidx.activity.ComponentActivity
-import androidx.activity.compose.setContent
-import androidx.compose.foundation.background
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.platform.ComposeView
-import androidx.compose.ui.unit.Dp
-import androidx.compose.ui.unit.dp
-import androidx.lifecycle.LifecycleOwner
-import com.android.compose.theme.LocalAndroidColorScheme
-import com.android.compose.theme.PlatformTheme
-import com.android.compose.ui.platform.DensityAwareComposeView
-import com.android.internal.policy.ScreenDecorationsUtils
-import com.android.systemui.bouncer.ui.BouncerDialogFactory
-import com.android.systemui.bouncer.ui.composable.BouncerContent
-import com.android.systemui.bouncer.ui.viewmodel.BouncerViewModel
-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.communal.ui.compose.CommunalContainer
-import com.android.systemui.communal.ui.compose.CommunalHub
-import com.android.systemui.communal.ui.viewmodel.BaseCommunalViewModel
-import com.android.systemui.communal.ui.viewmodel.CommunalViewModel
-import com.android.systemui.communal.widgets.WidgetConfigurator
-import com.android.systemui.keyboard.stickykeys.ui.view.createStickyKeyIndicatorView
-import com.android.systemui.keyboard.stickykeys.ui.viewmodel.StickyKeysIndicatorViewModel
-import com.android.systemui.keyguard.shared.model.LockscreenSceneBlueprint
-import com.android.systemui.keyguard.ui.composable.LockscreenContent
-import com.android.systemui.keyguard.ui.composable.blueprint.ComposableLockscreenSceneBlueprint
-import com.android.systemui.keyguard.ui.viewmodel.LockscreenContentViewModel
-import com.android.systemui.people.ui.compose.PeopleScreen
-import com.android.systemui.people.ui.viewmodel.PeopleViewModel
-import com.android.systemui.qs.footer.ui.compose.FooterActions
-import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel
-import com.android.systemui.scene.shared.model.Scene
-import com.android.systemui.scene.shared.model.SceneDataSourceDelegator
-import com.android.systemui.scene.shared.model.SceneKey
-import com.android.systemui.scene.ui.composable.ComposableScene
-import com.android.systemui.scene.ui.composable.SceneContainer
-import com.android.systemui.scene.ui.viewmodel.SceneContainerViewModel
-import com.android.systemui.volume.panel.ui.composable.VolumePanelRoot
-import com.android.systemui.volume.panel.ui.viewmodel.VolumePanelViewModel
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.flow.SharingStarted
-import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.map
-import kotlinx.coroutines.flow.stateIn
-
-/** The Compose facade, when Compose is available. */
-object ComposeFacade : BaseComposeFacade {
- override fun isComposeAvailable(): Boolean = true
-
- override fun composeInitializer(): ComposeInitializer = ComposeInitializerImpl
-
- override fun setPeopleSpaceActivityContent(
- activity: ComponentActivity,
- viewModel: PeopleViewModel,
- onResult: (PeopleViewModel.Result) -> Unit,
- ) {
- activity.setContent { PlatformTheme { PeopleScreen(viewModel, onResult) } }
- }
-
- override fun setCommunalEditWidgetActivityContent(
- activity: ComponentActivity,
- viewModel: BaseCommunalViewModel,
- widgetConfigurator: WidgetConfigurator,
- onOpenWidgetPicker: () -> Unit,
- onEditDone: () -> Unit,
- ) {
- activity.setContent {
- PlatformTheme {
- Box(
- modifier =
- Modifier.fillMaxSize()
- .background(LocalAndroidColorScheme.current.outlineVariant),
- ) {
- CommunalHub(
- viewModel = viewModel,
- onOpenWidgetPicker = onOpenWidgetPicker,
- widgetConfigurator = widgetConfigurator,
- onEditDone = onEditDone,
- )
- }
- }
- }
- }
-
- override fun setVolumePanelActivityContent(
- activity: ComponentActivity,
- viewModel: VolumePanelViewModel,
- onDismiss: () -> Unit,
- ) {
- activity.setContent {
- VolumePanelRoot(
- viewModel = viewModel,
- onDismiss = onDismiss,
- )
- }
- }
-
- override fun createFooterActionsView(
- context: Context,
- viewModel: FooterActionsViewModel,
- qsVisibilityLifecycleOwner: LifecycleOwner,
- ): View {
- return DensityAwareComposeView(context).apply {
- setContent { PlatformTheme { FooterActions(viewModel, qsVisibilityLifecycleOwner) } }
- }
- }
-
- override fun createSceneContainerView(
- scope: CoroutineScope,
- context: Context,
- viewModel: SceneContainerViewModel,
- windowInsets: StateFlow<WindowInsets?>,
- sceneByKey: Map<SceneKey, Scene>,
- dataSourceDelegator: SceneDataSourceDelegator,
- ): View {
- return ComposeView(context).apply {
- setContent {
- PlatformTheme {
- ScreenDecorProvider(
- displayCutout = displayCutoutFromWindowInsets(scope, context, windowInsets),
- screenCornerRadius = ScreenDecorationsUtils.getWindowCornerRadius(context)
- ) {
- SceneContainer(
- viewModel = viewModel,
- sceneByKey =
- sceneByKey.mapValues { (_, scene) -> scene as ComposableScene },
- dataSourceDelegator = dataSourceDelegator,
- )
- }
- }
- }
- }
- }
-
- override fun createStickyKeysIndicatorContent(
- context: Context,
- viewModel: StickyKeysIndicatorViewModel
- ): View {
- return createStickyKeyIndicatorView(context, viewModel)
- }
-
- override fun createCommunalView(
- context: Context,
- viewModel: BaseCommunalViewModel,
- ): View {
- return ComposeView(context).apply {
- setContent { PlatformTheme { CommunalHub(viewModel = viewModel) } }
- }
- }
-
- override fun createCommunalContainer(context: Context, viewModel: CommunalViewModel): View {
- return ComposeView(context).apply {
- setContent { PlatformTheme { CommunalContainer(viewModel = viewModel) } }
- }
- }
-
- // TODO(b/298525212): remove once Compose exposes window inset bounds.
- private fun displayCutoutFromWindowInsets(
- scope: CoroutineScope,
- context: Context,
- windowInsets: StateFlow<WindowInsets?>,
- ): StateFlow<DisplayCutout> =
- windowInsets
- .map {
- val boundingRect = it?.displayCutout?.boundingRectTop
- val width = boundingRect?.let { boundingRect.right - boundingRect.left } ?: 0
- val left = boundingRect?.left?.toDp(context) ?: 0.dp
- val top = boundingRect?.top?.toDp(context) ?: 0.dp
- val right = boundingRect?.right?.toDp(context) ?: 0.dp
- val bottom = boundingRect?.bottom?.toDp(context) ?: 0.dp
- val location =
- when {
- width <= 0f -> CutoutLocation.NONE
- left <= 0.dp -> CutoutLocation.LEFT
- right >= getDisplayWidth(context) -> CutoutLocation.RIGHT
- else -> CutoutLocation.CENTER
- }
- DisplayCutout(
- left,
- top,
- right,
- bottom,
- location,
- )
- }
- .stateIn(scope, SharingStarted.WhileSubscribed(), DisplayCutout())
-
- // TODO(b/298525212): remove once Compose exposes window inset bounds.
- private fun getDisplayWidth(context: Context): Dp {
- val point = Point()
- checkNotNull(context.display).getRealSize(point)
- return point.x.dp
- }
-
- // TODO(b/298525212): remove once Compose exposes window inset bounds.
- private fun Int.toDp(context: Context): Dp {
- return (this.toFloat() / context.resources.displayMetrics.density).dp
- }
-
- override fun createBouncer(
- context: Context,
- viewModel: BouncerViewModel,
- dialogFactory: BouncerDialogFactory,
- ): View {
- return ComposeView(context).apply {
- setContent { PlatformTheme { BouncerContent(viewModel, dialogFactory) } }
- }
- }
-
- override fun createLockscreen(
- context: Context,
- viewModel: LockscreenContentViewModel,
- blueprints: Set<@JvmSuppressWildcards LockscreenSceneBlueprint>,
- ): View {
- val sceneBlueprints =
- blueprints.mapNotNull { it as? ComposableLockscreenSceneBlueprint }.toSet()
- return ComposeView(context).apply {
- setContent {
- LockscreenContent(viewModel = viewModel, blueprints = sceneBlueprints)
- .Content(modifier = Modifier.fillMaxSize())
- }
- }
- }
-}
diff --git a/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/compose/ComposeInitializerImpl.kt b/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/compose/ComposeInitializerImpl.kt
deleted file mode 100644
index 1674591c30b5..000000000000
--- a/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/compose/ComposeInitializerImpl.kt
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2023 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.compose
-
-import android.view.View
-import androidx.lifecycle.findViewTreeLifecycleOwner
-import androidx.lifecycle.setViewTreeLifecycleOwner
-import androidx.lifecycle.Lifecycle
-import androidx.savedstate.SavedStateRegistryController
-import androidx.savedstate.SavedStateRegistryOwner
-import com.android.compose.animation.ViewTreeSavedStateRegistryOwner
-import com.android.systemui.lifecycle.ViewLifecycleOwner
-
-internal object ComposeInitializerImpl : ComposeInitializer {
- override fun onAttachedToWindow(root: View) {
- if (root.findViewTreeLifecycleOwner() != null) {
- error("root $root already has a LifecycleOwner")
- }
-
- val parent = root.parent
- if (parent is View && parent.id != android.R.id.content) {
- error(
- "ComposeInitializer.onAttachedToWindow(View) must be called on the content child." +
- "Outside of activities and dialogs, this is usually the top-most View of a " +
- "window."
- )
- }
-
- // The lifecycle owner, which is STARTED when [root] is visible and RESUMED when [root] is
- // both visible and focused.
- val lifecycleOwner = ViewLifecycleOwner(root)
-
- // We create a trivial implementation of [SavedStateRegistryOwner] that does not do any save
- // or restore because SystemUI process is always running and top-level windows using this
- // initializer are created once, when the process is started.
- val savedStateRegistryOwner =
- object : SavedStateRegistryOwner {
- private val savedStateRegistryController =
- SavedStateRegistryController.create(this).apply { performRestore(null) }
-
- override val savedStateRegistry = savedStateRegistryController.savedStateRegistry
-
- override val lifecycle: Lifecycle
- get() = lifecycleOwner.lifecycle
- }
-
- // We must call [ViewLifecycleOwner.onCreate] after creating the [SavedStateRegistryOwner]
- // because `onCreate` might move the lifecycle state to STARTED which will make
- // [SavedStateRegistryController.performRestore] throw.
- lifecycleOwner.onCreate()
-
- // Set the owners on the root. They will be reused by any ComposeView inside the root
- // hierarchy.
- root.setViewTreeLifecycleOwner(lifecycleOwner)
- ViewTreeSavedStateRegistryOwner.set(root, savedStateRegistryOwner)
- }
-
- override fun onDetachedFromWindow(root: View) {
- (root.findViewTreeLifecycleOwner() as ViewLifecycleOwner).onDestroy()
- root.setViewTreeLifecycleOwner(null)
- ViewTreeSavedStateRegistryOwner.set(root, null)
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/BouncerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/BouncerViewBinder.kt
index 36d3ed52b655..f1a0e5e3539c 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/BouncerViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/BouncerViewBinder.kt
@@ -11,7 +11,6 @@ import com.android.systemui.bouncer.shared.flag.ComposeBouncerFlags
import com.android.systemui.bouncer.ui.BouncerDialogFactory
import com.android.systemui.bouncer.ui.viewmodel.BouncerViewModel
import com.android.systemui.bouncer.ui.viewmodel.KeyguardBouncerViewModel
-import com.android.systemui.compose.ComposeFacade
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.flags.Flags.COMPOSE_BOUNCER_ENABLED
import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel
@@ -60,11 +59,7 @@ constructor(
private val composeBouncerDependencies: Lazy<ComposeBouncerDependencies>,
) {
fun bind(view: ViewGroup) {
- if (
- COMPOSE_BOUNCER_ENABLED &&
- composeBouncerFlags.isOnlyComposeBouncerEnabled() &&
- ComposeFacade.isComposeAvailable()
- ) {
+ if (COMPOSE_BOUNCER_ENABLED && composeBouncerFlags.isOnlyComposeBouncerEnabled()) {
val deps = composeBouncerDependencies.get()
ComposeBouncerViewBinder.bind(
view,
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/ComposeBouncerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/ComposeBouncerViewBinder.kt
index 7b053956091e..179fa874db79 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/ComposeBouncerViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/ComposeBouncerViewBinder.kt
@@ -1,15 +1,17 @@
package com.android.systemui.bouncer.ui.binder
import android.view.ViewGroup
+import androidx.compose.ui.platform.ComposeView
import androidx.core.view.isVisible
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
+import com.android.compose.theme.PlatformTheme
import com.android.keyguard.ViewMediatorCallback
import com.android.systemui.authentication.domain.interactor.AuthenticationInteractor
import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
import com.android.systemui.bouncer.ui.BouncerDialogFactory
+import com.android.systemui.bouncer.ui.composable.BouncerContent
import com.android.systemui.bouncer.ui.viewmodel.BouncerViewModel
-import com.android.systemui.compose.ComposeFacade
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.user.domain.interactor.SelectedUserInteractor
import kotlinx.coroutines.flow.collectLatest
@@ -27,12 +29,11 @@ object ComposeBouncerViewBinder {
viewMediatorCallback: ViewMediatorCallback?,
) {
view.addView(
- ComposeFacade.createBouncer(
- view.context,
- viewModel,
- dialogFactory,
- )
+ ComposeView(view.context).apply {
+ setContent { PlatformTheme { BouncerContent(viewModel, dialogFactory) } }
+ }
)
+
view.repeatWhenAttached {
repeatOnLifecycle(Lifecycle.State.CREATED) {
launch {
diff --git a/packages/SystemUI/src/com/android/systemui/communal/widgets/EditWidgetsActivity.kt b/packages/SystemUI/src/com/android/systemui/communal/widgets/EditWidgetsActivity.kt
index a5a390d7683b..48b3e4c3616d 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/widgets/EditWidgetsActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/widgets/EditWidgetsActivity.kt
@@ -25,14 +25,21 @@ import android.util.Log
import android.view.IWindowManager
import android.view.WindowInsets
import androidx.activity.ComponentActivity
+import androidx.activity.compose.setContent
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.ui.Modifier
+import com.android.compose.theme.LocalAndroidColorScheme
+import com.android.compose.theme.PlatformTheme
import com.android.internal.logging.UiEventLogger
import com.android.systemui.communal.shared.log.CommunalUiEvent
import com.android.systemui.communal.shared.model.CommunalSceneKey
+import com.android.systemui.communal.ui.compose.CommunalHub
import com.android.systemui.communal.ui.viewmodel.CommunalEditModeViewModel
import com.android.systemui.communal.util.WidgetPickerIntentUtils.getWidgetExtraFromIntent
-import com.android.systemui.compose.ComposeFacade.setCommunalEditWidgetActivityContent
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.core.Logger
import com.android.systemui.log.dagger.CommunalLog
@@ -110,56 +117,68 @@ constructor(
val preselectedKey = intent.getStringExtra(EXTRA_PRESELECTED_KEY)
communalViewModel.setSelectedKey(preselectedKey)
- setCommunalEditWidgetActivityContent(
- activity = this,
- viewModel = communalViewModel,
- widgetConfigurator = widgetConfigurator,
- onOpenWidgetPicker = {
- val intent =
- Intent(Intent.ACTION_MAIN).also { it.addCategory(Intent.CATEGORY_HOME) }
- packageManager
- .resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY)
- ?.activityInfo
- ?.packageName
- ?.let { packageName ->
- try {
- addWidgetActivityLauncher.launch(
- Intent(Intent.ACTION_PICK).apply {
- setPackage(packageName)
- putExtra(
- EXTRA_DESIRED_WIDGET_WIDTH,
- resources.getDimensionPixelSize(
- R.dimen.communal_widget_picker_desired_width
- )
- )
- putExtra(
- EXTRA_DESIRED_WIDGET_HEIGHT,
- resources.getDimensionPixelSize(
- R.dimen.communal_widget_picker_desired_height
- )
- )
- putExtra(
- AppWidgetManager.EXTRA_CATEGORY_FILTER,
- communalViewModel.getCommunalWidgetCategories
- )
- }
+ setContent {
+ PlatformTheme {
+ Box(
+ modifier =
+ Modifier.fillMaxSize()
+ .background(LocalAndroidColorScheme.current.outlineVariant),
+ ) {
+ CommunalHub(
+ viewModel = communalViewModel,
+ onOpenWidgetPicker = ::onOpenWidgetPicker,
+ widgetConfigurator = widgetConfigurator,
+ onEditDone = ::onEditDone,
+ )
+ }
+ }
+ }
+ }
+
+ private fun onOpenWidgetPicker() {
+ val intent = Intent(Intent.ACTION_MAIN).also { it.addCategory(Intent.CATEGORY_HOME) }
+ packageManager
+ .resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY)
+ ?.activityInfo
+ ?.packageName
+ ?.let { packageName ->
+ try {
+ addWidgetActivityLauncher.launch(
+ Intent(Intent.ACTION_PICK).apply {
+ setPackage(packageName)
+ putExtra(
+ EXTRA_DESIRED_WIDGET_WIDTH,
+ resources.getDimensionPixelSize(
+ R.dimen.communal_widget_picker_desired_width
+ )
+ )
+ putExtra(
+ EXTRA_DESIRED_WIDGET_HEIGHT,
+ resources.getDimensionPixelSize(
+ R.dimen.communal_widget_picker_desired_height
+ )
+ )
+ putExtra(
+ AppWidgetManager.EXTRA_CATEGORY_FILTER,
+ communalViewModel.getCommunalWidgetCategories
)
- } catch (e: Exception) {
- Log.e(TAG, "Failed to launch widget picker activity", e)
}
- }
- ?: run { Log.e(TAG, "Couldn't resolve launcher package name") }
- },
- onEditDone = {
- try {
- communalViewModel.onSceneChanged(CommunalSceneKey.Communal)
- checkNotNull(windowManagerService).lockNow(/* options */ null)
- finish()
- } catch (e: RemoteException) {
- Log.e(TAG, "Couldn't lock the device as WindowManager is dead.")
+ )
+ } catch (e: Exception) {
+ Log.e(TAG, "Failed to launch widget picker activity", e)
}
}
- )
+ ?: run { Log.e(TAG, "Couldn't resolve launcher package name") }
+ }
+
+ private fun onEditDone() {
+ try {
+ communalViewModel.onSceneChanged(CommunalSceneKey.Communal)
+ checkNotNull(windowManagerService).lockNow(/* options */ null)
+ finish()
+ } catch (e: RemoteException) {
+ Log.e(TAG, "Couldn't lock the device as WindowManager is dead.")
+ }
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
diff --git a/packages/SystemUI/src/com/android/systemui/compose/BaseComposeFacade.kt b/packages/SystemUI/src/com/android/systemui/compose/BaseComposeFacade.kt
deleted file mode 100644
index a0aaa906802a..000000000000
--- a/packages/SystemUI/src/com/android/systemui/compose/BaseComposeFacade.kt
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package com.android.systemui.compose
-
-import android.content.Context
-import android.view.View
-import android.view.WindowInsets
-import androidx.activity.ComponentActivity
-import androidx.lifecycle.LifecycleOwner
-import com.android.systemui.bouncer.ui.BouncerDialogFactory
-import com.android.systemui.bouncer.ui.viewmodel.BouncerViewModel
-import com.android.systemui.communal.ui.viewmodel.BaseCommunalViewModel
-import com.android.systemui.communal.ui.viewmodel.CommunalViewModel
-import com.android.systemui.communal.widgets.WidgetConfigurator
-import com.android.systemui.keyboard.stickykeys.ui.viewmodel.StickyKeysIndicatorViewModel
-import com.android.systemui.keyguard.shared.model.LockscreenSceneBlueprint
-import com.android.systemui.keyguard.ui.viewmodel.LockscreenContentViewModel
-import com.android.systemui.people.ui.viewmodel.PeopleViewModel
-import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel
-import com.android.systemui.scene.shared.model.Scene
-import com.android.systemui.scene.shared.model.SceneDataSourceDelegator
-import com.android.systemui.scene.shared.model.SceneKey
-import com.android.systemui.scene.ui.viewmodel.SceneContainerViewModel
-import com.android.systemui.volume.panel.ui.viewmodel.VolumePanelViewModel
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.flow.StateFlow
-
-/**
- * A facade to interact with Compose, when it is available.
- *
- * You should access this facade by calling the static methods on
- * [com.android.systemui.compose.ComposeFacade] directly.
- */
-interface BaseComposeFacade {
- /**
- * Whether Compose is currently available. This function should be checked before calling any
- * other functions on this facade.
- *
- * This value will never change at runtime.
- */
- fun isComposeAvailable(): Boolean
-
- /**
- * Return the [ComposeInitializer] to make Compose usable in windows outside normal activities.
- */
- fun composeInitializer(): ComposeInitializer
-
- /** Bind the content of [activity] to [viewModel]. */
- fun setPeopleSpaceActivityContent(
- activity: ComponentActivity,
- viewModel: PeopleViewModel,
- onResult: (PeopleViewModel.Result) -> Unit,
- )
-
- /** Bind the content of [activity] to [viewModel]. */
- fun setCommunalEditWidgetActivityContent(
- activity: ComponentActivity,
- viewModel: BaseCommunalViewModel,
- widgetConfigurator: WidgetConfigurator,
- onOpenWidgetPicker: () -> Unit,
- onEditDone: () -> Unit,
- )
-
- fun setVolumePanelActivityContent(
- activity: ComponentActivity,
- viewModel: VolumePanelViewModel,
- onDismiss: () -> Unit,
- )
-
- /** Create a [View] to represent [viewModel] on screen. */
- fun createFooterActionsView(
- context: Context,
- viewModel: FooterActionsViewModel,
- qsVisibilityLifecycleOwner: LifecycleOwner,
- ): View
-
- /** Create a [View] to represent [viewModel] on screen. */
- fun createSceneContainerView(
- scope: CoroutineScope,
- context: Context,
- viewModel: SceneContainerViewModel,
- windowInsets: StateFlow<WindowInsets?>,
- sceneByKey: Map<SceneKey, Scene>,
- dataSourceDelegator: SceneDataSourceDelegator,
- ): View
-
- /** Creates sticky key indicator content presenting provided [viewModel] */
- fun createStickyKeysIndicatorContent(
- context: Context,
- viewModel: StickyKeysIndicatorViewModel
- ): View
-
- /** Create a [View] to represent [viewModel] on screen. */
- fun createCommunalView(
- context: Context,
- viewModel: BaseCommunalViewModel,
- ): View
-
- /** Create a [View] to represent the [BouncerViewModel]. */
- fun createBouncer(
- context: Context,
- viewModel: BouncerViewModel,
- dialogFactory: BouncerDialogFactory,
- ): View
-
- /** Creates a container that hosts the communal UI and handles gesture transitions. */
- fun createCommunalContainer(context: Context, viewModel: CommunalViewModel): View
-
- /** Creates a [View] that represents the Lockscreen. */
- fun createLockscreen(
- context: Context,
- viewModel: LockscreenContentViewModel,
- blueprints: Set<@JvmSuppressWildcards LockscreenSceneBlueprint>,
- ): View
-}
diff --git a/packages/SystemUI/src/com/android/systemui/compose/ComposeInitializer.kt b/packages/SystemUI/src/com/android/systemui/compose/ComposeInitializer.kt
index 90dc3a00daa2..813e0e025bf5 100644
--- a/packages/SystemUI/src/com/android/systemui/compose/ComposeInitializer.kt
+++ b/packages/SystemUI/src/com/android/systemui/compose/ComposeInitializer.kt
@@ -17,6 +17,13 @@
package com.android.systemui.compose
import android.view.View
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.findViewTreeLifecycleOwner
+import androidx.lifecycle.setViewTreeLifecycleOwner
+import androidx.savedstate.SavedStateRegistryController
+import androidx.savedstate.SavedStateRegistryOwner
+import com.android.compose.animation.ViewTreeSavedStateRegistryOwner
+import com.android.systemui.lifecycle.ViewLifecycleOwner
/**
* An initializer to use Compose outside of an Activity, e.g. inside a window added directly using
@@ -39,10 +46,55 @@ import android.view.View
* }
* ```
*/
-interface ComposeInitializer {
+object ComposeInitializer {
/** Function to be called on your window root view's [View.onAttachedToWindow] function. */
- fun onAttachedToWindow(root: View)
+ fun onAttachedToWindow(root: View) {
+ if (root.findViewTreeLifecycleOwner() != null) {
+ error("root $root already has a LifecycleOwner")
+ }
+
+ val parent = root.parent
+ if (parent is View && parent.id != android.R.id.content) {
+ error(
+ "ComposeInitializer.onAttachedToWindow(View) must be called on the content child." +
+ "Outside of activities and dialogs, this is usually the top-most View of a " +
+ "window."
+ )
+ }
+
+ // The lifecycle owner, which is STARTED when [root] is visible and RESUMED when [root] is
+ // both visible and focused.
+ val lifecycleOwner = ViewLifecycleOwner(root)
+
+ // We create a trivial implementation of [SavedStateRegistryOwner] that does not do any save
+ // or restore because SystemUI process is always running and top-level windows using this
+ // initializer are created once, when the process is started.
+ val savedStateRegistryOwner =
+ object : SavedStateRegistryOwner {
+ private val savedStateRegistryController =
+ SavedStateRegistryController.create(this).apply { performRestore(null) }
+
+ override val savedStateRegistry = savedStateRegistryController.savedStateRegistry
+
+ override val lifecycle: Lifecycle
+ get() = lifecycleOwner.lifecycle
+ }
+
+ // We must call [ViewLifecycleOwner.onCreate] after creating the [SavedStateRegistryOwner]
+ // because `onCreate` might move the lifecycle state to STARTED which will make
+ // [SavedStateRegistryController.performRestore] throw.
+ lifecycleOwner.onCreate()
+
+ // Set the owners on the root. They will be reused by any ComposeView inside the root
+ // hierarchy.
+ root.setViewTreeLifecycleOwner(lifecycleOwner)
+ ViewTreeSavedStateRegistryOwner.set(root, savedStateRegistryOwner)
+ }
/** Function to be called on your window root view's [View.onDetachedFromWindow] function. */
- fun onDetachedFromWindow(root: View)
+ fun onDetachedFromWindow(root: View) {
+ (root.findViewTreeLifecycleOwner() as ViewLifecycleOwner).onDestroy()
+ root.setViewTreeLifecycleOwner(null)
+ ViewTreeSavedStateRegistryOwner.set(root, null)
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/stickykeys/ui/StickyKeyDialogFactory.kt b/packages/SystemUI/src/com/android/systemui/keyboard/stickykeys/ui/StickyKeyDialogFactory.kt
index 3ed58a7fe5ae..f9084e5a6191 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/stickykeys/ui/StickyKeyDialogFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/stickykeys/ui/StickyKeyDialogFactory.kt
@@ -26,9 +26,9 @@ import android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
import android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
import android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL
import androidx.activity.ComponentDialog
-import com.android.systemui.compose.ComposeFacade
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.keyboard.stickykeys.ui.view.createStickyKeyIndicatorView
import com.android.systemui.keyboard.stickykeys.ui.viewmodel.StickyKeysIndicatorViewModel
import com.android.systemui.res.R
import javax.inject.Inject
@@ -48,7 +48,7 @@ constructor(
return ComponentDialog(context, R.style.Theme_SystemUI_Dialog).apply {
// because we're requesting window feature it must be called before setting content
window?.setStickyKeyWindowAttributes()
- setContentView(ComposeFacade.createStickyKeysIndicatorContent(context, viewModel))
+ setContentView(createStickyKeyIndicatorView(context, viewModel))
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/stickykeys/ui/StickyKeysIndicatorCoordinator.kt b/packages/SystemUI/src/com/android/systemui/keyboard/stickykeys/ui/StickyKeysIndicatorCoordinator.kt
index 842fd04bfcc5..78c4e77cad74 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/stickykeys/ui/StickyKeysIndicatorCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/stickykeys/ui/StickyKeysIndicatorCoordinator.kt
@@ -17,15 +17,13 @@
package com.android.systemui.keyboard.stickykeys.ui
import android.app.Dialog
-import android.util.Log
-import com.android.systemui.compose.ComposeFacade
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.keyboard.stickykeys.StickyKeysLogger
import com.android.systemui.keyboard.stickykeys.ui.viewmodel.StickyKeysIndicatorViewModel
+import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
-import javax.inject.Inject
@SysUISingleton
class StickyKeysIndicatorCoordinator
@@ -40,11 +38,6 @@ constructor(
private var dialog: Dialog? = null
fun startListening() {
- // this check needs to be moved to PhysicalKeyboardCoreStartable
- if (!ComposeFacade.isComposeAvailable()) {
- Log.e("StickyKeysIndicatorCoordinator", "Compose is required for this UI")
- return
- }
applicationScope.launch {
viewModel.indicatorContent.collect { stickyKeys ->
stickyKeysLogger.logNewUiState(stickyKeys)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt
index 301942f6242b..106fdf1fbcbe 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt
@@ -20,6 +20,9 @@ package com.android.systemui.keyguard
import android.content.Context
import android.view.LayoutInflater
import android.view.View
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.ComposeView
import androidx.constraintlayout.widget.ConstraintSet
import androidx.constraintlayout.widget.ConstraintSet.BOTTOM
import androidx.constraintlayout.widget.ConstraintSet.END
@@ -35,7 +38,6 @@ import com.android.keyguard.dagger.KeyguardStatusViewComponent
import com.android.systemui.CoreStartable
import com.android.systemui.Flags.keyguardBottomAreaRefactor
import com.android.systemui.common.ui.ConfigurationState
-import com.android.systemui.compose.ComposeFacade
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryHapticsInteractor
import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor
@@ -45,6 +47,8 @@ import com.android.systemui.keyguard.shared.model.LockscreenSceneBlueprint
import com.android.systemui.keyguard.ui.binder.KeyguardBlueprintViewBinder
import com.android.systemui.keyguard.ui.binder.KeyguardIndicationAreaBinder
import com.android.systemui.keyguard.ui.binder.KeyguardRootViewBinder
+import com.android.systemui.keyguard.ui.composable.LockscreenContent
+import com.android.systemui.keyguard.ui.composable.blueprint.ComposableLockscreenSceneBlueprint
import com.android.systemui.keyguard.ui.view.KeyguardIndicationArea
import com.android.systemui.keyguard.ui.view.KeyguardRootView
import com.android.systemui.keyguard.ui.view.layout.KeyguardBlueprintCommandListener
@@ -132,7 +136,7 @@ constructor(
if (!SceneContainerFlag.isEnabled) {
if (ComposeLockscreen.isEnabled) {
val composeView =
- ComposeFacade.createLockscreen(
+ createLockscreen(
context = context,
viewModel = lockscreenContentViewModel,
blueprints = lockscreenSceneBlueprintsLazy.get(),
@@ -207,6 +211,21 @@ constructor(
)
}
+ private fun createLockscreen(
+ context: Context,
+ viewModel: LockscreenContentViewModel,
+ blueprints: Set<@JvmSuppressWildcards LockscreenSceneBlueprint>,
+ ): View {
+ val sceneBlueprints =
+ blueprints.mapNotNull { it as? ComposableLockscreenSceneBlueprint }.toSet()
+ return ComposeView(context).apply {
+ setContent {
+ LockscreenContent(viewModel = viewModel, blueprints = sceneBlueprints)
+ .Content(modifier = Modifier.fillMaxSize())
+ }
+ }
+ }
+
/**
* Temporary, to allow NotificationPanelViewController to use the same instance while code is
* migrated: b/288242803
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/ComposeLockscreen.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/ComposeLockscreen.kt
index 7f0b483919b3..601fbfaf1b64 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/ComposeLockscreen.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/ComposeLockscreen.kt
@@ -17,7 +17,6 @@
package com.android.systemui.keyguard.shared
import com.android.systemui.Flags
-import com.android.systemui.compose.ComposeFacade
import com.android.systemui.flags.FlagToken
import com.android.systemui.flags.RefactorFlagUtils
@@ -34,7 +33,7 @@ object ComposeLockscreen {
/** Is the refactor enabled */
@JvmStatic
inline val isEnabled
- get() = Flags.composeLockscreen() && ComposeFacade.isComposeAvailable()
+ get() = Flags.composeLockscreen()
/**
* Called to ensure code is only run when the flag is enabled. This protects users from the
diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.kt b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.kt
index 5b7eb454597c..deb0fed0ffc8 100644
--- a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.kt
@@ -20,14 +20,15 @@ import android.appwidget.AppWidgetManager
import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
+import androidx.activity.compose.setContent
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
-import com.android.systemui.compose.ComposeFacade.isComposeAvailable
-import com.android.systemui.compose.ComposeFacade.setPeopleSpaceActivityContent
+import com.android.compose.theme.PlatformTheme
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
+import com.android.systemui.people.ui.compose.PeopleScreen
import com.android.systemui.people.ui.view.PeopleViewBinder
import com.android.systemui.people.ui.view.PeopleViewBinder.bind
import com.android.systemui.people.ui.viewmodel.PeopleViewModel
@@ -65,13 +66,11 @@ constructor(
}
// Set the content of the activity, using either the View or Compose implementation.
- if (featureFlags.isEnabled(Flags.COMPOSE_PEOPLE_SPACE) && isComposeAvailable()) {
+ if (featureFlags.isEnabled(Flags.COMPOSE_PEOPLE_SPACE)) {
Log.d(TAG, "Using the Compose implementation of the PeopleSpaceActivity")
- setPeopleSpaceActivityContent(
- activity = this,
- viewModel,
- onResult = { finishActivity(it) },
- )
+ setContent {
+ PlatformTheme { PeopleScreen(viewModel, onResult = { finishActivity(it) }) }
+ }
} else {
Log.d(TAG, "Using the View implementation of the PeopleSpaceActivity")
val view = PeopleViewBinder.create(this)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSImpl.java
index 741336277119..a000d63a2ee3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSImpl.java
@@ -47,7 +47,6 @@ import com.android.app.animation.Interpolators;
import com.android.keyguard.BouncerPanelExpansionCalculator;
import com.android.systemui.Dumpable;
import com.android.systemui.animation.ShadeInterpolation;
-import com.android.systemui.compose.ComposeFacade;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
@@ -301,8 +300,7 @@ public class QSImpl implements QS, CommandQueue.Callbacks, StatusBarStateControl
private void bindFooterActionsView(View root) {
LinearLayout footerActionsView = root.findViewById(R.id.qs_footer_actions);
- if (!mFeatureFlags.isEnabled(Flags.COMPOSE_QS_FOOTER_ACTIONS)
- || !ComposeFacade.INSTANCE.isComposeAvailable()) {
+ if (!mFeatureFlags.isEnabled(Flags.COMPOSE_QS_FOOTER_ACTIONS)) {
Log.d(TAG, "Binding the View implementation of the QS footer actions");
mFooterActionsView = footerActionsView;
mFooterActionsViewBinder.bind(footerActionsView, mQSFooterActionsViewModel,
@@ -312,7 +310,7 @@ public class QSImpl implements QS, CommandQueue.Callbacks, StatusBarStateControl
// Compose is available, so let's use the Compose implementation of the footer actions.
Log.d(TAG, "Binding the Compose implementation of the QS footer actions");
- View composeView = ComposeFacade.INSTANCE.createFooterActionsView(root.getContext(),
+ View composeView = QSUtils.createFooterActionsView(root.getContext(),
mQSFooterActionsViewModel, mListeningAndVisibilityLifecycleOwner);
mFooterActionsView = composeView;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSUtils.kt b/packages/SystemUI/src/com/android/systemui/qs/QSUtils.kt
index e42264f24e92..15c3f271469d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSUtils.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSUtils.kt
@@ -1,7 +1,13 @@
package com.android.systemui.qs
import android.content.Context
+import android.view.View
+import androidx.lifecycle.LifecycleOwner
+import com.android.compose.theme.PlatformTheme
+import com.android.compose.ui.platform.DensityAwareComposeView
import com.android.internal.policy.SystemBarUtils
+import com.android.systemui.qs.footer.ui.compose.FooterActions
+import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel
import com.android.systemui.util.LargeScreenUtils.shouldUseLargeScreenShadeHeader
object QSUtils {
@@ -21,4 +27,15 @@ object QSUtils {
SystemBarUtils.getQuickQsOffsetHeight(context)
}
}
-} \ No newline at end of file
+
+ @JvmStatic
+ fun createFooterActionsView(
+ context: Context,
+ viewModel: FooterActionsViewModel,
+ qsVisibilityLifecycleOwner: LifecycleOwner,
+ ): View {
+ return DensityAwareComposeView(context).apply {
+ setContent { PlatformTheme { FooterActions(viewModel, qsVisibilityLifecycleOwner) } }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlags.kt b/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlags.kt
index 8408c51c86dc..1808d98cd692 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlags.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlags.kt
@@ -24,7 +24,6 @@ import com.android.systemui.Flags.FLAG_SCENE_CONTAINER
import com.android.systemui.Flags.keyguardBottomAreaRefactor
import com.android.systemui.Flags.migrateClocksToBlueprint
import com.android.systemui.Flags.sceneContainer
-import com.android.systemui.compose.ComposeFacade
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.flags.FlagToken
import com.android.systemui.flags.Flags.SCENE_CONTAINER_ENABLED
@@ -47,9 +46,8 @@ object SceneContainerFlag {
keyguardBottomAreaRefactor() &&
migrateClocksToBlueprint() &&
ComposeLockscreen.isEnabled &&
- MediaInSceneContainerFlag.isEnabled &&
- // NOTE: Changes should also be made in getSecondaryFlags and @EnableSceneContainer
- ComposeFacade.isComposeAvailable()
+ MediaInSceneContainerFlag.isEnabled
+ // NOTE: Changes should also be made in getSecondaryFlags and @EnableSceneContainer
/**
* The main static flag, SCENE_CONTAINER_ENABLED. This is an explicit static flag check that
@@ -74,11 +72,7 @@ object SceneContainerFlag {
/** The full set of requirements for SceneContainer */
inline fun getAllRequirements(): Sequence<FlagToken> {
- val composeRequirement =
- FlagToken("ComposeFacade.isComposeAvailable()", ComposeFacade.isComposeAvailable())
- return sequenceOf(getMainStaticFlag(), getMainAconfigFlag()) +
- getSecondaryFlags() +
- composeRequirement
+ return sequenceOf(getMainStaticFlag(), getMainAconfigFlag()) + getSecondaryFlags()
}
/** Return all dependencies of this flag in pairs where [Pair.first] depends on [Pair.second] */
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 ee76c0582b9d..f2697b4e1c1e 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
@@ -16,17 +16,26 @@
package com.android.systemui.scene.ui.view
+import android.content.Context
+import android.graphics.Point
import android.view.View
import android.view.ViewGroup
import android.view.WindowInsets
import androidx.activity.OnBackPressedDispatcher
import androidx.activity.OnBackPressedDispatcherOwner
import androidx.activity.setViewTreeOnBackPressedDispatcherOwner
+import androidx.compose.ui.platform.ComposeView
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.dp
import androidx.core.view.isVisible
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
-import com.android.systemui.compose.ComposeFacade
+import com.android.compose.theme.PlatformTheme
+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.lifecycle.repeatWhenAttached
import com.android.systemui.res.R
import com.android.systemui.scene.shared.flag.SceneContainerFlags
@@ -34,10 +43,16 @@ import com.android.systemui.scene.shared.model.Scene
import com.android.systemui.scene.shared.model.SceneContainerConfig
import com.android.systemui.scene.shared.model.SceneDataSourceDelegator
import com.android.systemui.scene.shared.model.SceneKey
+import com.android.systemui.scene.ui.composable.ComposableScene
+import com.android.systemui.scene.ui.composable.SceneContainer
import com.android.systemui.scene.ui.viewmodel.SceneContainerViewModel
import com.android.systemui.statusbar.notification.stack.shared.flexiNotifsEnabled
import com.android.systemui.statusbar.notification.stack.ui.view.SharedNotificationContainer
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
object SceneWindowRootViewBinder {
@@ -83,7 +98,7 @@ object SceneWindowRootViewBinder {
)
view.addView(
- ComposeFacade.createSceneContainerView(
+ createSceneContainerView(
scope = this,
context = view.context,
viewModel = viewModel,
@@ -120,4 +135,74 @@ object SceneWindowRootViewBinder {
}
}
}
+
+ private fun createSceneContainerView(
+ scope: CoroutineScope,
+ context: Context,
+ viewModel: SceneContainerViewModel,
+ windowInsets: StateFlow<WindowInsets?>,
+ sceneByKey: Map<SceneKey, Scene>,
+ dataSourceDelegator: SceneDataSourceDelegator,
+ ): View {
+ return ComposeView(context).apply {
+ setContent {
+ PlatformTheme {
+ ScreenDecorProvider(
+ displayCutout = displayCutoutFromWindowInsets(scope, context, windowInsets),
+ screenCornerRadius = ScreenDecorationsUtils.getWindowCornerRadius(context)
+ ) {
+ SceneContainer(
+ viewModel = viewModel,
+ sceneByKey =
+ sceneByKey.mapValues { (_, scene) -> scene as ComposableScene },
+ dataSourceDelegator = dataSourceDelegator,
+ )
+ }
+ }
+ }
+ }
+ }
+
+ // TODO(b/298525212): remove once Compose exposes window inset bounds.
+ private fun displayCutoutFromWindowInsets(
+ scope: CoroutineScope,
+ context: Context,
+ windowInsets: StateFlow<WindowInsets?>,
+ ): StateFlow<DisplayCutout> =
+ windowInsets
+ .map {
+ val boundingRect = it?.displayCutout?.boundingRectTop
+ val width = boundingRect?.let { boundingRect.right - boundingRect.left } ?: 0
+ val left = boundingRect?.left?.toDp(context) ?: 0.dp
+ val top = boundingRect?.top?.toDp(context) ?: 0.dp
+ val right = boundingRect?.right?.toDp(context) ?: 0.dp
+ val bottom = boundingRect?.bottom?.toDp(context) ?: 0.dp
+ val location =
+ when {
+ width <= 0f -> CutoutLocation.NONE
+ left <= 0.dp -> CutoutLocation.LEFT
+ right >= getDisplayWidth(context) -> CutoutLocation.RIGHT
+ else -> CutoutLocation.CENTER
+ }
+ DisplayCutout(
+ left,
+ top,
+ right,
+ bottom,
+ location,
+ )
+ }
+ .stateIn(scope, SharingStarted.WhileSubscribed(), DisplayCutout())
+
+ // TODO(b/298525212): remove once Compose exposes window inset bounds.
+ private fun getDisplayWidth(context: Context): Dp {
+ val point = Point()
+ checkNotNull(context.display).getRealSize(point)
+ return point.x.dp
+ }
+
+ // TODO(b/298525212): remove once Compose exposes window inset bounds.
+ private fun Int.toDp(context: Context): Dp {
+ return (this.toFloat() / context.resources.displayMetrics.density).dp
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/view/WindowRootView.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/view/WindowRootView.kt
index 4c2c97981702..22645c4532f6 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/ui/view/WindowRootView.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/ui/view/WindowRootView.kt
@@ -25,7 +25,7 @@ import android.view.View
import android.view.WindowInsets
import android.widget.FrameLayout
import androidx.core.view.updateMargins
-import com.android.systemui.compose.ComposeFacade
+import com.android.systemui.compose.ComposeInitializer
import com.android.systemui.res.R
/** A view that can serve as the root of the main SysUI window. */
@@ -45,16 +45,16 @@ open class WindowRootView(
override fun onAttachedToWindow() {
super.onAttachedToWindow()
- if (ComposeFacade.isComposeAvailable() && isRoot()) {
- ComposeFacade.composeInitializer().onAttachedToWindow(this)
+ if (isRoot()) {
+ ComposeInitializer.onAttachedToWindow(this)
}
}
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
- if (ComposeFacade.isComposeAvailable() && isRoot()) {
- ComposeFacade.composeInitializer().onDetachedFromWindow(this)
+ if (isRoot()) {
+ ComposeInitializer.onDetachedFromWindow(this)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt b/packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt
index df845f559f2e..d3869baf16a2 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt
@@ -23,11 +23,12 @@ import android.view.GestureDetector
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
+import androidx.compose.ui.platform.ComposeView
+import com.android.compose.theme.PlatformTheme
import com.android.internal.annotations.VisibleForTesting
import com.android.systemui.communal.domain.interactor.CommunalInteractor
+import com.android.systemui.communal.ui.compose.CommunalContainer
import com.android.systemui.communal.ui.viewmodel.CommunalViewModel
-import com.android.systemui.compose.ComposeFacade.createCommunalContainer
-import com.android.systemui.compose.ComposeFacade.isComposeAvailable
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.res.R
@@ -35,7 +36,6 @@ import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.util.kotlin.collectFlow
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.flowOf
/**
* Controller that's responsible for the glanceable hub container view and its touch handling.
@@ -107,8 +107,7 @@ constructor(
private var shadeShowing = false
/** Returns a flow that tracks whether communal hub is available. */
- fun communalAvailable(): Flow<Boolean> =
- if (isComposeAvailable()) communalInteractor.isCommunalAvailable else flowOf(false)
+ fun communalAvailable(): Flow<Boolean> = communalInteractor.isCommunalAvailable
/**
* Creates the container view containing the glanceable hub UI.
@@ -118,7 +117,11 @@ constructor(
fun initView(
context: Context,
): View {
- return initView(createCommunalContainer(context, communalViewModel))
+ return initView(
+ ComposeView(context).apply {
+ setContent { PlatformTheme { CommunalContainer(viewModel = communalViewModel) } }
+ }
+ )
}
/** Override for testing. */
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/shared/flag/VolumePanelFlag.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/shared/flag/VolumePanelFlag.kt
index d90a9c75deec..485f4b5cbfd7 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/shared/flag/VolumePanelFlag.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/shared/flag/VolumePanelFlag.kt
@@ -17,23 +17,18 @@
package com.android.systemui.volume.panel.shared.flag
import com.android.systemui.Flags
-import com.android.systemui.compose.ComposeFacade
import com.android.systemui.flags.RefactorFlagUtils
import javax.inject.Inject
/** Provides a flag to check for the new Compose based Volume Panel availability. */
class VolumePanelFlag @Inject constructor() {
- /**
- * Returns true when the new Volume Panel is available and false the otherwise. The new panel
- * can only be available when [ComposeFacade.isComposeAvailable] is true.
- */
+ /** Returns true when the new Volume Panel is available and false the otherwise. */
fun canUseNewVolumePanel(): Boolean {
- return ComposeFacade.isComposeAvailable() && Flags.newVolumePanel()
+ return Flags.newVolumePanel()
}
fun assertNewVolumePanel() {
- require(ComposeFacade.isComposeAvailable())
RefactorFlagUtils.assertInNewMode(Flags.newVolumePanel(), Flags.FLAG_NEW_VOLUME_PANEL)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/ui/activity/VolumePanelActivity.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/ui/activity/VolumePanelActivity.kt
index 53e1b8b5bb70..d430e65770fd 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/ui/activity/VolumePanelActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/ui/activity/VolumePanelActivity.kt
@@ -18,11 +18,12 @@ package com.android.systemui.volume.panel.ui.activity
import android.os.Bundle
import androidx.activity.ComponentActivity
+import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.activity.viewModels
-import com.android.systemui.compose.ComposeFacade
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.volume.panel.shared.flag.VolumePanelFlag
+import com.android.systemui.volume.panel.ui.composable.VolumePanelRoot
import com.android.systemui.volume.panel.ui.viewmodel.VolumePanelViewModel
import javax.inject.Inject
import javax.inject.Provider
@@ -44,7 +45,7 @@ constructor(
volumePanelFlag.assertNewVolumePanel()
- ComposeFacade.setVolumePanelActivityContent(this, viewModel) { finish() }
+ setContent { VolumePanelRoot(viewModel = viewModel, onDismiss = ::finish) }
}
override fun onContentChanged() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/compose/ComposeInitializerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/compose/ComposeInitializerTest.kt
index 3e6cc3bb4f6b..03e4f9ae1685 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/compose/ComposeInitializerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/compose/ComposeInitializerTest.kt
@@ -32,10 +32,6 @@ import org.junit.runner.RunWith
class ComposeInitializerTest : SysuiTestCase() {
@Test
fun testCanAddComposeViewInInitializedWindow() {
- if (!ComposeFacade.isComposeAvailable()) {
- return
- }
-
val root = TestWindowRoot(context)
try {
runOnMainThreadAndWaitForIdleSync { ViewUtils.attachView(root) }
@@ -55,12 +51,12 @@ class ComposeInitializerTest : SysuiTestCase() {
class TestWindowRoot(context: Context) : FrameLayout(context) {
override fun onAttachedToWindow() {
super.onAttachedToWindow()
- ComposeFacade.composeInitializer().onAttachedToWindow(this)
+ ComposeInitializer.onAttachedToWindow(this)
}
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
- ComposeFacade.composeInitializer().onDetachedFromWindow(this)
+ ComposeInitializer.onDetachedFromWindow(this)
}
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyboard/stickykeys/ui/StickyKeysIndicatorCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyboard/stickykeys/ui/StickyKeysIndicatorCoordinatorTest.kt
index a992956f5121..59d8fc3d3fd0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyboard/stickykeys/ui/StickyKeysIndicatorCoordinatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyboard/stickykeys/ui/StickyKeysIndicatorCoordinatorTest.kt
@@ -19,7 +19,6 @@ package com.android.systemui.keyboard.stickykeys.ui
import android.app.Dialog
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
-import com.android.systemui.compose.ComposeFacade
import com.android.systemui.keyboard.data.repository.FakeStickyKeysRepository
import com.android.systemui.keyboard.data.repository.keyboardRepository
import com.android.systemui.keyboard.stickykeys.StickyKeysLogger
@@ -34,7 +33,6 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
-import org.junit.Assume
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -54,19 +52,22 @@ class StickyKeysIndicatorCoordinatorTest : SysuiTestCase() {
@Before
fun setup() {
- Assume.assumeTrue(ComposeFacade.isComposeAvailable())
val dialogFactory = mock<StickyKeyDialogFactory>()
whenever(dialogFactory.create(any())).thenReturn(dialog)
val keyboardRepository = Kosmos().keyboardRepository
- val viewModel = StickyKeysIndicatorViewModel(
+ val viewModel =
+ StickyKeysIndicatorViewModel(
stickyKeysRepository,
keyboardRepository,
- testScope.backgroundScope)
- coordinator = StickyKeysIndicatorCoordinator(
+ testScope.backgroundScope
+ )
+ coordinator =
+ StickyKeysIndicatorCoordinator(
testScope.backgroundScope,
dialogFactory,
viewModel,
- mock<StickyKeysLogger>())
+ mock<StickyKeysLogger>()
+ )
coordinator.startListening()
keyboardRepository.setIsAnyKeyboardConnected(true)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/GlanceableHubContainerControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/GlanceableHubContainerControllerTest.kt
index 665fc750c742..96574e245d2d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/GlanceableHubContainerControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/GlanceableHubContainerControllerTest.kt
@@ -35,7 +35,6 @@ import com.android.systemui.communal.domain.interactor.communalInteractor
import com.android.systemui.communal.domain.interactor.setCommunalAvailable
import com.android.systemui.communal.shared.model.CommunalSceneKey
import com.android.systemui.communal.ui.viewmodel.CommunalViewModel
-import com.android.systemui.compose.ComposeFacade
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.testDispatcher
@@ -52,9 +51,7 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import org.junit.After
import org.junit.Assert.assertThrows
-import org.junit.Assume.assumeTrue
import org.junit.Before
-import org.junit.BeforeClass
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
@@ -305,13 +302,5 @@ class GlanceableHubContainerControllerTest : SysuiTestCase() {
MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, CONTAINER_HEIGHT.toFloat(), 0)
private val MOVE_EVENT = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_MOVE, 0f, 0f, 0)
private val UP_EVENT = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_UP, 0f, 0f, 0)
-
- @BeforeClass
- @JvmStatic
- fun beforeClass() {
- // Glanceable hub requires Compose, no point running any of these tests if compose isn't
- // enabled.
- assumeTrue(ComposeFacade.isComposeAvailable())
- }
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
index b426d1de0b00..960fd59b4f10 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
@@ -16,6 +16,7 @@
package com.android.systemui.shade
+import org.mockito.Mockito.`when` as whenever
import android.content.Context
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper.RunWithLooper
@@ -33,7 +34,6 @@ import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor
import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
import com.android.systemui.bouncer.ui.binder.BouncerViewBinder
import com.android.systemui.classifier.FalsingCollectorFake
-import com.android.systemui.compose.ComposeFacade.isComposeAvailable
import com.android.systemui.dock.DockManager
import com.android.systemui.dump.DumpManager
import com.android.systemui.flags.FakeFeatureFlagsClassic
@@ -88,7 +88,6 @@ import org.mockito.Mockito.mock
import org.mockito.Mockito.never
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
-import org.mockito.Mockito.`when` as whenever
import org.mockito.MockitoAnnotations
@OptIn(ExperimentalCoroutinesApi::class)
@@ -511,10 +510,6 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
@Test
@Ignore("b/321332798")
fun setsUpCommunalHubLayout_whenFlagEnabled() {
- if (!isComposeAvailable()) {
- return
- }
-
whenever(mGlanceableHubContainerController.communalAvailable())
.thenReturn(MutableStateFlow(true))
@@ -537,10 +532,6 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
@Test
fun doesNotSetupCommunalHubLayout_whenFlagDisabled() {
- if (!isComposeAvailable()) {
- return
- }
-
whenever(mGlanceableHubContainerController.communalAvailable())
.thenReturn(MutableStateFlow(false))
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/flags/SceneContainerRule.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/flags/SceneContainerRule.kt
index 3faa6eb8f5f2..4e05de27bb33 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/flags/SceneContainerRule.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/flags/SceneContainerRule.kt
@@ -17,7 +17,6 @@
package com.android.systemui.flags
import android.util.Log
-import com.android.systemui.compose.ComposeFacade
import com.android.systemui.scene.shared.flag.SceneContainerFlag
import org.junit.Assert
import org.junit.Assume
@@ -42,10 +41,6 @@ class SceneContainerRule : TestRule {
null || description?.getAnnotation(EnableSceneContainer::class.java) != null
if (hasAnnotation) {
Assume.assumeTrue(
- "Compose must be available for @EnableSceneContainer test",
- ComposeFacade.isComposeAvailable()
- )
- Assume.assumeTrue(
"Couldn't set Flags.SCENE_CONTAINER_ENABLED for @EnableSceneContainer test",
trySetSceneContainerEnabled(true)
)