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