diff --git a/packages/SystemUI/compose/facade/disabled/src/com/android/systemui/compose/ComposeFacade.kt b/packages/SystemUI/compose/facade/disabled/src/com/android/systemui/compose/ComposeFacade.kt index 89b2d83657907..e253fb925ceb1 100644 --- a/packages/SystemUI/compose/facade/disabled/src/com/android/systemui/compose/ComposeFacade.kt +++ b/packages/SystemUI/compose/facade/disabled/src/com/android/systemui/compose/ComposeFacade.kt @@ -17,8 +17,12 @@ package com.android.systemui.compose +import android.content.Context +import android.view.View import androidx.activity.ComponentActivity +import androidx.lifecycle.LifecycleOwner import com.android.systemui.people.ui.viewmodel.PeopleViewModel +import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel /** The Compose facade, when Compose is *not* available. */ object ComposeFacade : BaseComposeFacade { @@ -36,6 +40,14 @@ object ComposeFacade : BaseComposeFacade { throwComposeUnavailableError() } + override fun createFooterActionsView( + context: Context, + viewModel: FooterActionsViewModel, + qsVisibilityLifecycleOwner: LifecycleOwner + ): View { + throwComposeUnavailableError() + } + private fun throwComposeUnavailableError(): Nothing { error( "Compose is not available. Make sure to check isComposeAvailable() before calling any" + 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 index 1c2000f04a813..1ea18fec4abe7 100644 --- 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 @@ -16,11 +16,17 @@ package com.android.systemui.compose +import android.content.Context +import android.view.View import androidx.activity.ComponentActivity import androidx.activity.compose.setContent +import androidx.compose.ui.platform.ComposeView +import androidx.lifecycle.LifecycleOwner import com.android.compose.theme.PlatformTheme 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 /** The Compose facade, when Compose is available. */ object ComposeFacade : BaseComposeFacade { @@ -35,4 +41,14 @@ object ComposeFacade : BaseComposeFacade { ) { activity.setContent { PlatformTheme { PeopleScreen(viewModel, onResult) } } } + + override fun createFooterActionsView( + context: Context, + viewModel: FooterActionsViewModel, + qsVisibilityLifecycleOwner: LifecycleOwner, + ): View { + return ComposeView(context).apply { + setContent { PlatformTheme { FooterActions(viewModel, qsVisibilityLifecycleOwner) } } + } + } } diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/FooterActions.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/FooterActions.kt index 5c5ceefbd6fb6..349f5c3331165 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/FooterActions.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/FooterActions.kt @@ -73,6 +73,7 @@ import com.android.systemui.R import com.android.systemui.animation.Expandable import com.android.systemui.common.shared.model.Icon import com.android.systemui.common.ui.compose.Icon +import com.android.systemui.compose.modifiers.sysuiResTag import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsButtonViewModel import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsForegroundServicesButtonViewModel import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsSecurityButtonViewModel @@ -180,9 +181,9 @@ fun FooterActions( security?.let { SecurityButton(it, Modifier.weight(1f)) } foregroundServices?.let { ForegroundServicesButton(it) } - userSwitcher?.let { IconButton(it) } - IconButton(viewModel.settings) - viewModel.power?.let { IconButton(it) } + userSwitcher?.let { IconButton(it, Modifier.sysuiResTag("multi_user_switch")) } + IconButton(viewModel.settings, Modifier.sysuiResTag("settings_button_container")) + viewModel.power?.let { IconButton(it, Modifier.sysuiResTag("pm_lite")) } } } } diff --git a/packages/SystemUI/src/com/android/systemui/compose/BaseComposeFacade.kt b/packages/SystemUI/src/com/android/systemui/compose/BaseComposeFacade.kt index 3080beec718be..c0f854958c419 100644 --- a/packages/SystemUI/src/com/android/systemui/compose/BaseComposeFacade.kt +++ b/packages/SystemUI/src/com/android/systemui/compose/BaseComposeFacade.kt @@ -17,8 +17,12 @@ package com.android.systemui.compose +import android.content.Context +import android.view.View import androidx.activity.ComponentActivity +import androidx.lifecycle.LifecycleOwner import com.android.systemui.people.ui.viewmodel.PeopleViewModel +import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel /** * A facade to interact with Compose, when it is available. @@ -46,4 +50,11 @@ interface BaseComposeFacade { viewModel: PeopleViewModel, onResult: (PeopleViewModel.Result) -> Unit, ) + + /** Create a [View] to represent [viewModel] on screen. */ + fun createFooterActionsView( + context: Context, + viewModel: FooterActionsViewModel, + qsVisibilityLifecycleOwner: LifecycleOwner, + ): View } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java index f8fb4e89111e1..4ad23136a3adc 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java @@ -47,6 +47,7 @@ import com.android.systemui.Dumpable; import com.android.systemui.R; import com.android.systemui.animation.Interpolators; 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.media.controls.ui.MediaHost; @@ -225,9 +226,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca mQSFooterActionsViewModel = mFooterActionsViewModelFactory.create(/* lifecycleOwner */ this); - LinearLayout footerActionsView = view.findViewById(R.id.qs_footer_actions); - FooterActionsViewBinder.bind(footerActionsView, mQSFooterActionsViewModel, - mListeningAndVisibilityLifecycleOwner); + bindFooterActionsView(view); mFooterActionsController.init(); mQSPanelScrollView = view.findViewById(R.id.expanded_qs_scroll_view); @@ -288,6 +287,33 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca }); } + private void bindFooterActionsView(View root) { + LinearLayout footerActionsView = root.findViewById(R.id.qs_footer_actions); + + if (!ComposeFacade.INSTANCE.isComposeAvailable()) { + Log.d(TAG, "Binding the View implementation of the QS footer actions"); + FooterActionsViewBinder.bind(footerActionsView, mQSFooterActionsViewModel, + mListeningAndVisibilityLifecycleOwner); + return; + } + + // 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(), + mQSFooterActionsViewModel, mListeningAndVisibilityLifecycleOwner); + + // The id R.id.qs_footer_actions is used by QSContainerImpl to set the horizontal margin + // to all views except for qs_footer_actions, so we set it to the Compose view. + composeView.setId(R.id.qs_footer_actions); + + // Replace the View by the Compose provided one. + ViewGroup parent = (ViewGroup) footerActionsView.getParent(); + ViewGroup.LayoutParams layoutParams = footerActionsView.getLayoutParams(); + int index = parent.indexOfChild(footerActionsView); + parent.removeViewAt(index); + parent.addView(composeView, index, layoutParams); + } + @Override public void setScrollListener(ScrollListener listener) { mScrollListener = listener;