Introduce communal tutorial content

This change allows the communal hub to show placeholder tutorial content
when user enters the hub for the first time.

Test: verified locally that tutorial content is shown
Bug: 303506432
Fix: 303506432
Change-Id: I8f4843c9a8588c8a1f4b0f1e590cc79449c2a839
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 3d670b8..c6e429a 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
@@ -22,6 +22,7 @@
 import android.view.WindowInsets
 import androidx.activity.ComponentActivity
 import androidx.lifecycle.LifecycleOwner
+import com.android.systemui.communal.ui.viewmodel.CommunalViewModel
 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
@@ -66,6 +67,7 @@
 
     override fun createCommunalView(
         context: Context,
+        viewModel: CommunalViewModel,
     ): View {
         throwComposeUnavailableError()
     }
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 7b11ac7..1722685 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
@@ -31,6 +31,7 @@
 import com.android.systemui.common.ui.compose.windowinsets.DisplayCutout
 import com.android.systemui.common.ui.compose.windowinsets.DisplayCutoutProvider
 import com.android.systemui.communal.ui.compose.CommunalHub
+import com.android.systemui.communal.ui.viewmodel.CommunalViewModel
 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
@@ -96,8 +97,11 @@
 
     override fun createCommunalView(
         context: Context,
+        viewModel: CommunalViewModel,
     ): View {
-        return ComposeView(context).apply { setContent { PlatformTheme { CommunalHub() } } }
+        return ComposeView(context).apply {
+            setContent { PlatformTheme { CommunalHub(viewModel = viewModel) } }
+        }
     }
 
     // TODO(b/298525212): remove once Compose exposes window inset bounds.
diff --git a/packages/SystemUI/compose/features/Android.bp b/packages/SystemUI/compose/features/Android.bp
index 796abf4b..16c2437 100644
--- a/packages/SystemUI/compose/features/Android.bp
+++ b/packages/SystemUI/compose/features/Android.bp
@@ -31,6 +31,7 @@
     ],
 
     static_libs: [
+        "CommunalLayoutLib",
         "SystemUI-core",
         "PlatformComposeCore",
         "PlatformComposeSceneTransitionLayout",
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
index 4d2978d..3d827fb 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
@@ -3,20 +3,63 @@
 import androidx.compose.foundation.background
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.material3.Text
+import androidx.compose.material3.Card
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.collectAsState
+import androidx.compose.runtime.getValue
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.res.dimensionResource
+import androidx.compose.ui.res.integerResource
+import com.android.systemui.communal.layout.ui.compose.CommunalGridLayout
+import com.android.systemui.communal.layout.ui.compose.config.CommunalGridLayoutCard
+import com.android.systemui.communal.layout.ui.compose.config.CommunalGridLayoutConfig
+import com.android.systemui.communal.ui.viewmodel.CommunalViewModel
+import com.android.systemui.res.R
 
 @Composable
-fun CommunalHub(modifier: Modifier = Modifier) {
+fun CommunalHub(
+    modifier: Modifier = Modifier,
+    viewModel: CommunalViewModel,
+) {
+    val showTutorial by viewModel.showTutorialContent.collectAsState(initial = false)
     Box(
         modifier = modifier.fillMaxSize().background(Color.White),
     ) {
-        Text(
-            modifier = Modifier.align(Alignment.Center),
-            text = "Hello Communal!",
+        CommunalGridLayout(
+            modifier = Modifier.align(Alignment.CenterStart),
+            layoutConfig =
+                CommunalGridLayoutConfig(
+                    gridColumnSize = dimensionResource(R.dimen.communal_grid_column_size),
+                    gridGutter = dimensionResource(R.dimen.communal_grid_gutter_size),
+                    gridHeight = dimensionResource(R.dimen.communal_grid_height),
+                    gridColumnsPerCard = integerResource(R.integer.communal_grid_columns_per_card),
+                ),
+            communalCards = if (showTutorial) tutorialContent else emptyList(),
         )
     }
 }
+
+private val tutorialContent =
+    listOf(
+        tutorialCard(CommunalGridLayoutCard.Size.FULL),
+        tutorialCard(CommunalGridLayoutCard.Size.THIRD),
+        tutorialCard(CommunalGridLayoutCard.Size.THIRD),
+        tutorialCard(CommunalGridLayoutCard.Size.THIRD),
+        tutorialCard(CommunalGridLayoutCard.Size.HALF),
+        tutorialCard(CommunalGridLayoutCard.Size.HALF),
+        tutorialCard(CommunalGridLayoutCard.Size.HALF),
+        tutorialCard(CommunalGridLayoutCard.Size.HALF),
+    )
+
+private fun tutorialCard(size: CommunalGridLayoutCard.Size): CommunalGridLayoutCard {
+    return object : CommunalGridLayoutCard() {
+        override val supportedSizes = listOf(size)
+
+        @Composable
+        override fun Content(modifier: Modifier) {
+            Card(modifier = modifier, content = {})
+        }
+    }
+}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalScene.kt
index d1c12ac..f3bef7b 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalScene.kt
@@ -19,6 +19,7 @@
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
 import com.android.compose.animation.scene.SceneScope
+import com.android.systemui.communal.ui.viewmodel.CommunalViewModel
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.scene.shared.model.Direction
 import com.android.systemui.scene.shared.model.SceneKey
@@ -32,7 +33,11 @@
 
 /** The communal scene shows glanceable hub when the device is locked and docked. */
 @SysUISingleton
-class CommunalScene @Inject constructor() : ComposableScene {
+class CommunalScene
+@Inject
+constructor(
+    private val viewModel: CommunalViewModel,
+) : ComposableScene {
     override val key = SceneKey.Communal
 
     override val destinationScenes: StateFlow<Map<UserAction, SceneModel>> =
@@ -45,6 +50,6 @@
 
     @Composable
     override fun SceneScope.Content(modifier: Modifier) {
-        CommunalHub(modifier)
+        CommunalHub(modifier, viewModel)
     }
 }
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 6377df3..4be648d 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -1661,6 +1661,15 @@
     <!-- Height percentage of the parent container occupied by the communal view -->
     <item name="communal_source_height_percentage" format="float" type="dimen">0.80</item>
 
+    <!-- Size of each communal grid column -->
+    <dimen name="communal_grid_column_size">64dp</dimen>
+    <!-- Size of each communal grid gutter between columns -->
+    <dimen name="communal_grid_gutter_size">16dp</dimen>
+    <!-- Height of the communal grid layout -->
+    <dimen name="communal_grid_height">630dp</dimen>
+    <!-- Number of columns for each communal card -->
+    <integer name="communal_grid_columns_per_card">6</integer>
+
     <dimen name="drag_and_drop_icon_size">70dp</dimen>
 
     <dimen name="qs_tile_service_request_dialog_width">304dp</dimen>
diff --git a/packages/SystemUI/src/com/android/systemui/communal/dagger/CommunalModule.kt b/packages/SystemUI/src/com/android/systemui/communal/dagger/CommunalModule.kt
new file mode 100644
index 0000000..b8e2de4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/communal/dagger/CommunalModule.kt
@@ -0,0 +1,32 @@
+/*
+ * 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.communal.dagger
+
+import com.android.systemui.communal.data.repository.CommunalRepositoryModule
+import com.android.systemui.communal.data.repository.CommunalTutorialRepositoryModule
+import com.android.systemui.communal.data.repository.CommunalWidgetRepositoryModule
+import dagger.Module
+
+@Module(
+    includes =
+        [
+            CommunalRepositoryModule::class,
+            CommunalTutorialRepositoryModule::class,
+            CommunalWidgetRepositoryModule::class,
+        ]
+)
+class CommunalModule
diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/sections/DefaultCommunalHubSection.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/sections/DefaultCommunalHubSection.kt
index 932dbfb..ad02f62 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/sections/DefaultCommunalHubSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/sections/DefaultCommunalHubSection.kt
@@ -2,6 +2,7 @@
 
 import androidx.constraintlayout.widget.ConstraintLayout
 import androidx.constraintlayout.widget.ConstraintSet
+import com.android.systemui.communal.ui.viewmodel.CommunalViewModel
 import com.android.systemui.compose.ComposeFacade
 import com.android.systemui.keyguard.shared.model.KeyguardSection
 import com.android.systemui.keyguard.ui.view.layout.sections.removeView
@@ -9,14 +10,20 @@
 import javax.inject.Inject
 
 /** A keyguard section that hosts the communal hub. */
-class DefaultCommunalHubSection @Inject constructor() : KeyguardSection() {
+class DefaultCommunalHubSection
+@Inject
+constructor(
+    private val viewModel: CommunalViewModel,
+) : KeyguardSection() {
     private val communalHubViewId = R.id.communal_hub
 
     override fun addViews(constraintLayout: ConstraintLayout) {
         constraintLayout.addView(
-            ComposeFacade.createCommunalView(constraintLayout.context).apply {
-                id = communalHubViewId
-            },
+            ComposeFacade.createCommunalView(
+                    context = constraintLayout.context,
+                    viewModel = viewModel,
+                )
+                .apply { id = communalHubViewId },
         )
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt
new file mode 100644
index 0000000..ddeb1d6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt
@@ -0,0 +1,32 @@
+/*
+ * 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.communal.ui.viewmodel
+
+import com.android.systemui.communal.domain.interactor.CommunalTutorialInteractor
+import com.android.systemui.dagger.SysUISingleton
+import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+
+@SysUISingleton
+class CommunalViewModel
+@Inject
+constructor(
+    tutorialInteractor: CommunalTutorialInteractor,
+) {
+    /** Whether communal hub should show tutorial content. */
+    val showTutorialContent: Flow<Boolean> = tutorialInteractor.isTutorialAvailable
+}
diff --git a/packages/SystemUI/src/com/android/systemui/compose/BaseComposeFacade.kt b/packages/SystemUI/src/com/android/systemui/compose/BaseComposeFacade.kt
index 5c1539a..9221832b 100644
--- a/packages/SystemUI/src/com/android/systemui/compose/BaseComposeFacade.kt
+++ b/packages/SystemUI/src/com/android/systemui/compose/BaseComposeFacade.kt
@@ -22,6 +22,7 @@
 import android.view.WindowInsets
 import androidx.activity.ComponentActivity
 import androidx.lifecycle.LifecycleOwner
+import com.android.systemui.communal.ui.viewmodel.CommunalViewModel
 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
@@ -73,8 +74,9 @@
         sceneByKey: Map<SceneKey, Scene>,
     ): View
 
-    /** Create a [View] that represents the communal hub. */
+    /** Create a [View] to represent [viewModel] on screen. */
     fun createCommunalView(
         context: Context,
+        viewModel: CommunalViewModel,
     ): View
 }
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index 7d4e1a1..f0d7592 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -42,6 +42,7 @@
 import com.android.systemui.classifier.FalsingModule;
 import com.android.systemui.clipboardoverlay.dagger.ClipboardOverlayModule;
 import com.android.systemui.common.ui.data.repository.CommonRepositoryModule;
+import com.android.systemui.communal.dagger.CommunalModule;
 import com.android.systemui.complication.dagger.ComplicationComponent;
 import com.android.systemui.controls.dagger.ControlsModule;
 import com.android.systemui.dagger.qualifiers.Main;
@@ -170,6 +171,7 @@
         ClipboardOverlayModule.class,
         ClockRegistryModule.class,
         CommonRepositoryModule.class,
+        CommunalModule.class,
         ConnectivityModule.class,
         ControlsModule.class,
         CoroutinesModule.class,
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 081edd1..019d428 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
@@ -38,9 +38,6 @@
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.classifier.FalsingCollector;
 import com.android.systemui.classifier.FalsingModule;
-import com.android.systemui.communal.data.repository.CommunalRepositoryModule;
-import com.android.systemui.communal.data.repository.CommunalTutorialRepositoryModule;
-import com.android.systemui.communal.data.repository.CommunalWidgetRepositoryModule;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dagger.qualifiers.UiBackground;
@@ -96,9 +93,6 @@
         KeyguardStatusViewComponent.class,
         KeyguardUserSwitcherComponent.class},
         includes = {
-            CommunalRepositoryModule.class,
-            CommunalTutorialRepositoryModule.class,
-            CommunalWidgetRepositoryModule.class,
             FalsingModule.class,
             KeyguardDataQuickAffordanceModule.class,
             KeyguardRepositoryModule.class,