Merge "Add the guts control panel to Smartspace media recommendation card." into sc-dev
diff --git a/packages/SystemUI/res/layout/media_smartspace_recommendations.xml b/packages/SystemUI/res/layout/media_smartspace_recommendations.xml
index 7e944162..f4a7434 100644
--- a/packages/SystemUI/res/layout/media_smartspace_recommendations.xml
+++ b/packages/SystemUI/res/layout/media_smartspace_recommendations.xml
@@ -18,6 +18,7 @@
 <!-- Layout for media recommendations inside QSPanel carousel -->
 <com.android.systemui.util.animation.TransitionLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:id="@+id/media_recommendations"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
@@ -84,4 +85,99 @@
         android:layout_width="@dimen/qs_aa_media_rec_icon_size"
         android:layout_height="@dimen/qs_aa_media_rec_icon_size" />
 
+    <!-- Constraints are set here as they are the same regardless of host -->
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="@dimen/qs_media_panel_outer_padding"
+        android:layout_marginStart="@dimen/qs_media_panel_outer_padding"
+        android:layout_marginEnd="@dimen/qs_media_panel_outer_padding"
+        android:id="@+id/recommendation_text"
+        android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
+        android:textColor="?android:attr/textColorSecondary"
+        android:text="@string/controls_media_title"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintBottom_toTopOf="@id/remove_text"
+        app:layout_constraintVertical_chainStyle="spread_inside"/>
+
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="@dimen/qs_media_panel_outer_padding"
+        android:layout_marginEnd="@dimen/qs_media_panel_outer_padding"
+        android:id="@+id/remove_text"
+        android:fontFamily="@*android:string/config_headlineFontFamily"
+        android:singleLine="true"
+        android:textColor="?android:attr/textColorPrimary"
+        android:text="@string/controls_media_close_session"
+        app:layout_constraintTop_toBottomOf="@id/recommendation_text"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintBottom_toTopOf="@id/settings"/>
+
+    <FrameLayout
+        android:id="@+id/settings"
+        android:background="@drawable/qs_media_light_source"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="@dimen/qs_media_panel_outer_padding"
+        android:paddingBottom="@dimen/qs_media_panel_outer_padding"
+        android:minWidth="48dp"
+        android:minHeight="48dp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/remove_text">
+
+        <TextView
+            android:layout_gravity="bottom"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
+            android:textColor="?android:attr/textColorPrimary"
+            android:text="@string/controls_media_settings_button" />
+    </FrameLayout>
+
+    <FrameLayout
+        android:id="@+id/cancel"
+        android:background="@drawable/qs_media_light_source"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginEnd="@dimen/qs_media_panel_outer_padding"
+        android:paddingBottom="@dimen/qs_media_panel_outer_padding"
+        android:minWidth="48dp"
+        android:minHeight="48dp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toStartOf="@id/dismiss" >
+
+        <TextView
+            android:layout_gravity="bottom"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
+            android:textColor="?android:attr/textColorPrimary"
+            android:text="@string/cancel" />
+    </FrameLayout>
+
+    <FrameLayout
+        android:id="@+id/dismiss"
+        android:background="@drawable/qs_media_light_source"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginEnd="@dimen/qs_media_panel_outer_padding"
+        android:paddingBottom="@dimen/qs_media_panel_outer_padding"
+        android:minWidth="48dp"
+        android:minHeight="48dp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent">
+
+        <TextView
+            android:layout_gravity="bottom"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
+            android:textColor="?android:attr/textColorPrimary"
+            android:text="@string/controls_media_dismiss_button"
+            />
+    </FrameLayout>
+
 </com.android.systemui.util.animation.TransitionLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
index 2ecd405..c3c617c 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
@@ -319,7 +319,7 @@
         val lp = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
             ViewGroup.LayoutParams.WRAP_CONTENT)
         newRecs.recommendationViewHolder?.recommendations?.setLayoutParams(lp)
-        newRecs.bindRecommendation(data, bgColor, { v -> removePlayer(key) })
+        newRecs.bindRecommendation(data, bgColor)
         MediaPlayerData.addMediaPlayer(key, newRecs)
         updatePlayerToState(newRecs, noAnimation = true)
         reorderAllPlayers()
@@ -348,11 +348,11 @@
 
             if (dismissMediaData) {
                 // Inform the media manager of a potentially late dismissal
-                mediaManager.dismissMediaData(key, 0L)
+                mediaManager.dismissMediaData(key, 0L /* delaye */)
             }
             if (dismissRecommendation) {
                 // Inform the media manager of a potentially late dismissal
-                mediaManager.dismissSmartspaceRecommendation()
+                mediaManager.dismissSmartspaceRecommendation(0L /* delay */)
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
index 94cb2dc..e6eb317 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
@@ -242,6 +242,21 @@
         TransitionLayout recommendations = vh.getRecommendations();
 
         mMediaViewController.attach(recommendations, MediaViewController.TYPE.RECOMMENDATION);
+
+        mRecommendationViewHolder.getRecommendations().setOnLongClickListener(v -> {
+            if (!mMediaViewController.isGutsVisible()) {
+                mMediaViewController.openGuts();
+                return true;
+            } else {
+                return false;
+            }
+        });
+        mRecommendationViewHolder.getCancel().setOnClickListener(v -> {
+            closeGuts();
+        });
+        mRecommendationViewHolder.getSettings().setOnClickListener(v -> {
+            mActivityStarter.startActivity(SETTINGS_INTENT, true /* dismissShade */);
+        });
     }
 
     /** Bind this player view based on the data given. */
@@ -461,10 +476,7 @@
     }
 
     /** Bind this recommendation view based on the data given. */
-    public void bindRecommendation(
-            @NonNull SmartspaceTarget target,
-            @NonNull int backgroundColor,
-            @Nullable View.OnClickListener callback) {
+    public void bindRecommendation(@NonNull SmartspaceTarget target, @NonNull int backgroundColor) {
         if (mRecommendationViewHolder == null) {
             return;
         }
@@ -520,8 +532,10 @@
             mediaCoverImageView.setImageIcon(recommendation.getIcon());
 
             // Set up the click listener if applicable.
-            setSmartspaceOnClickListener(mediaCoverImageView, recommendation,
-                    target.getSmartspaceTargetId(), callback);
+            setSmartspaceRecItemOnClickListener(mediaCoverImageView, recommendation,
+                    view -> mMediaDataManagerLazy
+                            .get()
+                            .dismissSmartspaceRecommendation(0L /* delay */));
 
             setVisibleAndAlpha(expandedSet, mediaCoverItemsResIds.get(i), true);
             setVisibleAndAlpha(expandedSet, mediaLogoItemsResIds.get(i), true);
@@ -529,6 +543,16 @@
             setVisibleAndAlpha(collapsedSet, mediaLogoItemsResIds.get(i), true);
         }
 
+        // Set up long press to show guts setting panel.
+        mRecommendationViewHolder.getDismiss().setOnClickListener(v -> {
+            closeGuts();
+            mKeyguardDismissUtil.executeWhenUnlocked(() -> {
+                mMediaDataManagerLazy.get().dismissSmartspaceRecommendation(
+                        MediaViewController.GUTS_ANIMATION_DURATION + 100L);
+                return true;
+            }, true /* requiresShadeOpen */);
+        });
+
         mController = null;
         mMediaViewController.refreshState();
     }
@@ -613,10 +637,9 @@
         set.setAlpha(actionId, visible ? 1.0f : 0.0f);
     }
 
-    private void setSmartspaceOnClickListener(
+    private void setSmartspaceRecItemOnClickListener(
             @NonNull View view,
             @NonNull SmartspaceAction action,
-            @NonNull String targetId,
             @Nullable View.OnClickListener callback) {
         if (view == null || action == null || action.getIntent() == null) {
             Log.e(TAG, "No tap action can be set up");
@@ -624,16 +647,6 @@
         }
 
         view.setOnClickListener(v -> {
-            // When media recommendation card is shown, there could be only one card.
-            SysUiStatsLog.write(SysUiStatsLog.SMARTSPACE_CARD_REPORTED,
-                    760, // SMARTSPACE_CARD_CLICK
-                    targetId.hashCode(),
-                    SysUiStatsLog
-                            .SMART_SPACE_CARD_REPORTED__CARD_TYPE__HEADPHONE_MEDIA_RECOMMENDATIONS,
-                    getSurfaceForSmartspaceLogging(mMediaViewController.getCurrentEndLocation()),
-                    /* rank */ 1,
-                    /* cardinality */ 1);
-
             mActivityStarter.postStartActivityDismissingKeyguard(
                     action.getIntent(),
                     0 /* delay */,
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt
index 5f73ae0..2bd7729 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt
@@ -191,7 +191,7 @@
             mediaDataManager.setTimedOut(it, timedOut = true, forceUpdate = true)
         }
         if (hasSmartspace) {
-            mediaDataManager.dismissSmartspaceRecommendation()
+            mediaDataManager.dismissSmartspaceRecommendation(0L /* delay */)
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
index 7807176..a070861 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
@@ -429,12 +429,13 @@
      * This will make the recommendation view to not be shown anymore during this headphone
      * connection session.
      */
-    fun dismissSmartspaceRecommendation() {
+    fun dismissSmartspaceRecommendation(delay: Long) {
         Log.d(TAG, "Dismissing Smartspace media target")
         // Do not set smartspaceMediaTarget to null. So the instance is preserved during the entire
         // headphone connection, and will ONLY be set to null when headphones are disconnected.
         smartspaceMediaTarget?.let {
-            notifySmartspaceMediaDataRemoved(it.smartspaceTargetId)
+            foregroundExecutor.executeDelayed(
+                { notifySmartspaceMediaDataRemoved(it.smartspaceTargetId) }, delay)
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaViewController.kt b/packages/SystemUI/src/com/android/systemui/media/MediaViewController.kt
index e848e2f..f78556f 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaViewController.kt
@@ -252,16 +252,30 @@
      * [TransitionViewState].
      */
     private fun setGutsViewState(viewState: TransitionViewState) {
-        PlayerViewHolder.controlsIds.forEach { id ->
-            viewState.widgetStates.get(id)?.let { state ->
-                // Make sure to use the unmodified state if guts are not visible
-                state.alpha = if (isGutsVisible) 0f else state.alpha
-                state.gone = if (isGutsVisible) true else state.gone
+        if (type == TYPE.PLAYER) {
+            PlayerViewHolder.controlsIds.forEach { id ->
+                viewState.widgetStates.get(id)?.let { state ->
+                    // Make sure to use the unmodified state if guts are not visible.
+                    state.alpha = if (isGutsVisible) 0f else state.alpha
+                    state.gone = if (isGutsVisible) true else state.gone
+                }
             }
-        }
-        PlayerViewHolder.gutsIds.forEach { id ->
-            viewState.widgetStates.get(id)?.alpha = if (isGutsVisible) 1f else 0f
-            viewState.widgetStates.get(id)?.gone = !isGutsVisible
+            PlayerViewHolder.gutsIds.forEach { id ->
+                viewState.widgetStates.get(id)?.alpha = if (isGutsVisible) 1f else 0f
+                viewState.widgetStates.get(id)?.gone = !isGutsVisible
+            }
+        } else {
+            RecommendationViewHolder.controlsIds.forEach { id ->
+                viewState.widgetStates.get(id)?.let { state ->
+                    // Make sure to use the unmodified state if guts are not visible.
+                    state.alpha = if (isGutsVisible) 0f else state.alpha
+                    state.gone = if (isGutsVisible) true else state.gone
+                }
+            }
+            RecommendationViewHolder.gutsIds.forEach { id ->
+                viewState.widgetStates.get(id)?.alpha = if (isGutsVisible) 1f else 0f
+                viewState.widgetStates.get(id)?.gone = !isGutsVisible
+            }
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/media/RecommendationViewHolder.kt b/packages/SystemUI/src/com/android/systemui/media/RecommendationViewHolder.kt
index ac201a8..19c83bc 100644
--- a/packages/SystemUI/src/com/android/systemui/media/RecommendationViewHolder.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/RecommendationViewHolder.kt
@@ -20,6 +20,7 @@
 import android.view.View
 import android.view.ViewGroup
 import android.widget.ImageView
+import android.widget.TextView
 import androidx.annotation.IntegerRes
 import com.android.systemui.R
 import com.android.systemui.util.animation.TransitionLayout
@@ -28,6 +29,8 @@
 class RecommendationViewHolder private constructor(itemView: View) {
 
     val recommendations = itemView as TransitionLayout
+
+    // Recommendation screen
     val mediaCoverItems = listOf<ImageView>(
         itemView.requireViewById(R.id.media_cover1),
         itemView.requireViewById(R.id.media_cover2),
@@ -49,16 +52,27 @@
         R.id.media_logo3,
         R.id.media_logo4)
 
+    // Settings/Guts screen
+    val cancel = itemView.requireViewById<View>(R.id.cancel)
+    val dismiss = itemView.requireViewById<ViewGroup>(R.id.dismiss)
+    val dismissLabel = dismiss.getChildAt(0)
+    val recommendationText = itemView.requireViewById<TextView>(R.id.recommendation_text)
+    val settings = itemView.requireViewById<View>(R.id.settings)
+
     init {
         (recommendations.background as IlluminationDrawable).let { background ->
             mediaCoverItems.forEach { background.registerLightSource(it) }
             mediaLogoItems.forEach { background.registerLightSource(it) }
+            background.registerLightSource(cancel)
+            background.registerLightSource(dismiss)
+            background.registerLightSource(dismissLabel)
+            background.registerLightSource(settings)
         }
     }
 
     companion object {
         /**
-         * Creates a PlayerViewHolder.
+         * Creates a RecommendationViewHolder.
          *
          * @param inflater LayoutInflater to use to inflate the layout.
          * @param parent Parent of inflated view.
@@ -76,5 +90,26 @@
             itemView.layoutDirection = View.LAYOUT_DIRECTION_LOCALE
             return RecommendationViewHolder(itemView)
         }
+
+        // Res Ids for the control components on the recommendation view.
+        val controlsIds = setOf(
+            R.id.media_cover1,
+            R.id.media_cover2,
+            R.id.media_cover3,
+            R.id.media_cover4,
+            R.id.media_logo1,
+            R.id.media_logo2,
+            R.id.media_logo3,
+            R.id.media_logo4
+        )
+
+        // Res Ids for the components on the guts panel.
+        val gutsIds = setOf(
+            R.id.recommendation_text,
+            R.id.remove_text,
+            R.id.cancel,
+            R.id.dismiss,
+            R.id.settings
+        )
     }
 }
\ No newline at end of file