diff options
13 files changed, 504 insertions, 202 deletions
diff --git a/packages/SystemUI/res/layout/media_session_view.xml b/packages/SystemUI/res/layout/media_session_view.xml index 9ad01528686e..f030f3130be4 100644 --- a/packages/SystemUI/res/layout/media_session_view.xml +++ b/packages/SystemUI/res/layout/media_session_view.xml @@ -44,6 +44,7 @@ android:background="@drawable/qs_media_scrim" /> + <!-- Guideline for output switcher --> <androidx.constraintlayout.widget.Guideline android:id="@+id/center_vertical_guideline" android:layout_width="wrap_content" @@ -51,6 +52,14 @@ android:orientation="vertical" app:layout_constraintGuide_percent="0.6" /> + <!-- Guideline for action buttons (collapsed view only) --> + <androidx.constraintlayout.widget.Guideline + android:id="@+id/action_button_guideline" + android:layout_width="0dp" + android:layout_height="0dp" + android:orientation="vertical" + app:layout_constraintGuide_end="@dimen/qs_media_session_collapsed_guideline" /> + <!-- App icon --> <com.android.internal.widget.CachingIconView android:id="@+id/icon" @@ -118,15 +127,7 @@ android:singleLine="true" android:textSize="16sp" android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginTop="20dp" - android:layout_marginStart="@dimen/qs_media_padding" - android:layout_marginEnd="@dimen/qs_media_padding" - app:layout_constrainedWidth="true" - app:layout_constraintTop_toBottomOf="@id/icon" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintEnd_toStartOf="@id/actionPlayPause" - app:layout_constraintHorizontal_bias="0" /> + android:layout_height="wrap_content" /> <!-- Artist name --> <TextView @@ -136,15 +137,7 @@ style="@style/MediaPlayer.Subtitle" android:textSize="14sp" android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginEnd="@dimen/qs_media_padding" - app:layout_constrainedWidth="true" - android:layout_marginTop="0dp" - app:layout_constraintTop_toBottomOf="@id/header_title" - app:layout_constraintStart_toStartOf="@id/header_title" - app:layout_constraintEnd_toStartOf="@id/actionPlayPause" - app:layout_constraintBottom_toBottomOf="@id/actionPlayPause" - app:layout_constraintHorizontal_bias="0" /> + android:layout_height="wrap_content" /> <ImageButton android:id="@+id/actionPlayPause" @@ -153,9 +146,33 @@ android:layout_height="48dp" android:layout_marginStart="@dimen/qs_media_padding" android:layout_marginEnd="@dimen/qs_media_padding" - android:layout_marginTop="0dp" - android:layout_marginBottom="0dp" /> + /> + + <!-- See comment in media_session_collapsed.xml for how these barriers are used --> + <androidx.constraintlayout.widget.Barrier + android:id="@+id/media_action_barrier" + android:layout_width="0dp" + android:layout_height="0dp" + android:orientation="vertical" + app:layout_constraintTop_toBottomOf="@id/header_title" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:barrierDirection="start" + app:constraint_referenced_ids="actionPrev,media_progress_bar,actionNext,action0,action1,action2,action3,action4" + /> + <androidx.constraintlayout.widget.Barrier + android:id="@+id/media_action_barrier_end" + android:layout_width="0dp" + android:layout_height="0dp" + android:orientation="vertical" + app:layout_constraintTop_toBottomOf="@id/media_seamless" + app:layout_constraintBottom_toBottomOf="parent" + app:barrierDirection="end" + app:constraint_referenced_ids="actionPrev,media_progress_bar,actionNext,action0,action1,action2,action3,action4" + app:layout_constraintStart_toStartOf="parent" + /> + <!-- Button visibility will be controlled in code --> <ImageButton android:id="@+id/actionPrev" style="@style/MediaPlayer.SessionAction" @@ -163,10 +180,9 @@ android:layout_height="48dp" android:layout_marginStart="4dp" android:layout_marginEnd="0dp" - android:layout_marginBottom="0dp" + android:layout_marginBottom="@dimen/qs_media_padding" android:layout_marginTop="0dp" - app:layout_constraintHorizontal_bias="1" - app:layout_constraintHorizontal_chainStyle="packed" /> + /> <!-- Seek Bar --> <!-- As per Material Design on Bidirectionality, this is forced to LTR in code --> @@ -174,12 +190,12 @@ android:id="@+id/media_progress_bar" style="@style/MediaPlayer.ProgressBar" android:layout_width="0dp" - android:layout_height="wrap_content" + android:layout_height="48dp" android:paddingTop="@dimen/qs_media_session_enabled_seekbar_vertical_padding" android:paddingBottom="12dp" android:maxHeight="@dimen/qs_media_enabled_seekbar_height" android:splitTrack="false" - android:layout_marginBottom="0dp" + android:layout_marginBottom="@dimen/qs_media_padding" android:layout_marginTop="0dp" android:layout_marginStart="0dp" android:layout_marginEnd="0dp" /> @@ -191,29 +207,58 @@ android:layout_height="48dp" android:layout_marginStart="0dp" android:layout_marginEnd="@dimen/qs_media_action_spacing" - android:layout_marginBottom="0dp" + android:layout_marginBottom="@dimen/qs_media_padding" android:layout_marginTop="0dp" /> <ImageButton - android:id="@+id/actionStart" + android:id="@+id/action0" style="@style/MediaPlayer.SessionAction" android:layout_width="48dp" android:layout_height="48dp" android:layout_marginStart="@dimen/qs_media_action_spacing" android:layout_marginEnd="@dimen/qs_media_action_spacing" - android:layout_marginBottom="0dp" + android:layout_marginBottom="@dimen/qs_media_padding" + android:layout_marginTop="0dp"/> + + <ImageButton + android:id="@+id/action1" + style="@style/MediaPlayer.SessionAction" + android:layout_width="48dp" + android:layout_height="48dp" + android:layout_marginStart="@dimen/qs_media_action_spacing" + android:layout_marginEnd="4dp" + android:layout_marginBottom="@dimen/qs_media_padding" android:layout_marginTop="0dp" /> <ImageButton - android:id="@+id/actionEnd" + android:id="@+id/action2" style="@style/MediaPlayer.SessionAction" android:layout_width="48dp" android:layout_height="48dp" android:layout_marginStart="@dimen/qs_media_action_spacing" android:layout_marginEnd="4dp" - android:layout_marginBottom="0dp" - android:layout_marginTop="0dp" - app:layout_constraintHorizontal_chainStyle="packed" /> + android:layout_marginBottom="@dimen/qs_media_padding" + android:layout_marginTop="0dp" /> + + <ImageButton + android:id="@+id/action3" + style="@style/MediaPlayer.SessionAction" + android:layout_width="48dp" + android:layout_height="48dp" + android:layout_marginStart="@dimen/qs_media_action_spacing" + android:layout_marginEnd="4dp" + android:layout_marginBottom="@dimen/qs_media_padding" + android:layout_marginTop="0dp" /> + + <ImageButton + android:id="@+id/action4" + style="@style/MediaPlayer.SessionAction" + android:layout_width="48dp" + android:layout_height="48dp" + android:layout_marginStart="@dimen/qs_media_action_spacing" + android:layout_marginEnd="4dp" + android:layout_marginBottom="@dimen/qs_media_padding" + android:layout_marginTop="0dp" /> <!-- Long press menu --> <TextView diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 00ab9760afbe..512f9160162c 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -983,6 +983,7 @@ <dimen name="qs_media_seekbar_progress_amplitude">1.5dp</dimen> <dimen name="qs_media_seekbar_progress_phase">8dp</dimen> <dimen name="qs_media_seekbar_progress_stroke_width">2dp</dimen> + <dimen name="qs_media_session_collapsed_guideline">144dp</dimen> <!-- Size of Smartspace media recommendations cards in the QSPanel carousel --> <dimen name="qs_aa_media_rec_album_size_collapsed">72dp</dimen> diff --git a/packages/SystemUI/res/xml/media_session_collapsed.xml b/packages/SystemUI/res/xml/media_session_collapsed.xml index c6e18a6f8740..f00e03116337 100644 --- a/packages/SystemUI/res/xml/media_session_collapsed.xml +++ b/packages/SystemUI/res/xml/media_session_collapsed.xml @@ -19,6 +19,13 @@ xmlns:app="http://schemas.android.com/apk/res-auto"> <Constraint + android:id="@+id/media_action_barrier" + android:layout_width="0dp" + android:layout_height="0dp" + app:layout_constraintTop_toBottomOf="@id/media_seamless" + app:layout_constraintStart_toEndOf="@id/action_button_guideline" /> + + <Constraint android:id="@+id/album_art" android:layout_width="match_parent" android:layout_height="@dimen/qs_media_session_height_collapsed" @@ -28,33 +35,73 @@ app:layout_constraintBottom_toBottomOf="parent" /> <Constraint + android:id="@+id/header_title" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="20dp" + android:layout_marginStart="@dimen/qs_media_padding" + android:layout_marginEnd="@dimen/qs_media_padding" + app:layout_constraintEnd_toStartOf="@id/action_button_guideline" + app:layout_constrainedWidth="true" + app:layout_constraintTop_toBottomOf="@id/icon" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintHorizontal_bias="0" /> + <Constraint + android:id="@+id/header_artist" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginEnd="@dimen/qs_media_padding" + android:layout_marginTop="0dp" + app:layout_constraintEnd_toStartOf="@id/action_button_guideline" + app:layout_constrainedWidth="true" + app:layout_constraintTop_toBottomOf="@id/header_title" + app:layout_constraintStart_toStartOf="@id/header_title" + app:layout_constraintVertical_bias="0" + app:layout_constraintHorizontal_bias="0" /> + + <Constraint android:id="@+id/actionPlayPause" android:layout_width="48dp" android:layout_height="48dp" android:layout_marginEnd="@dimen/qs_media_padding" - app:layout_constraintStart_toEndOf="@id/actionEnd" + android:layout_marginBottom="@dimen/qs_media_padding" + app:layout_constraintVertical_bias="1" app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintTop_toBottomOf="@id/media_seamless" - app:layout_constraintBottom_toBottomOf="parent" /> + app:layout_constraintStart_toEndOf="@id/media_action_barrier_end" /> + <!-- + There will only be 3 action buttons shown at most in this layout (controlled in code). + Play/Pause should always be at the end, but the other buttons should remain in the same order + when in RTL. + This is accomplished by setting two barriers at the start and end of the small buttons, + anchored to a guideline set at 3x button width from the end. The text and play/pause button are + positioned relative to the barriers, and the small buttons use right/left constraints to stay + in the correct order inside the barriers. + --> <Constraint android:id="@+id/actionPrev" android:layout_width="48dp" android:layout_height="48dp" + android:layout_marginBottom="@dimen/qs_media_padding" app:layout_constraintHorizontal_bias="1" + app:layout_constraintVertical_bias="1" app:layout_constraintHorizontal_chainStyle="packed" - app:layout_constraintStart_toEndOf="@id/header_artist" - app:layout_constraintEnd_toStartOf="@id/media_progress_bar" + app:layout_constraintRight_toLeftOf="@id/media_progress_bar" app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintTop_toBottomOf="@id/media_seamless" /> + app:layout_constraintTop_toBottomOf="@id/media_seamless" + app:layout_constraintLeft_toRightOf="@id/media_action_barrier" /> <Constraint android:id="@+id/media_progress_bar" android:layout_width="0dp" android:layout_height="wrap_content" + android:layout_marginBottom="@dimen/qs_media_padding" android:visibility="gone" - app:layout_constraintStart_toEndOf="@id/actionPrev" - app:layout_constraintEnd_toStartOf="@id/actionNext" + app:layout_constraintVertical_bias="1" + app:layout_constraintLeft_toRightOf="@id/actionPrev" + app:layout_constraintRight_toLeftOf="@id/actionNext" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintTop_toBottomOf="@id/media_seamless" /> @@ -62,29 +109,70 @@ android:id="@+id/actionNext" android:layout_width="48dp" android:layout_height="48dp" - app:layout_constraintStart_toEndOf="@id/media_progress_bar" - app:layout_constraintEnd_toStartOf="@id/actionStart" + android:layout_marginBottom="@dimen/qs_media_padding" + app:layout_constraintVertical_bias="1" + app:layout_constraintLeft_toRightOf="@id/media_progress_bar" + app:layout_constraintRight_toLeftOf="@id/action0" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintTop_toBottomOf="@id/media_seamless" /> + + <Constraint + android:id="@+id/action0" + android:layout_width="48dp" + android:layout_height="48dp" + android:layout_marginBottom="@dimen/qs_media_padding" + android:visibility="gone" + app:layout_constraintVertical_bias="1" + app:layout_constraintLeft_toRightOf="@id/actionNext" + app:layout_constraintRight_toLeftOf="@id/action1" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintTop_toBottomOf="@id/media_seamless" /> + + <Constraint + android:id="@+id/action1" + android:layout_width="48dp" + android:layout_height="48dp" + android:layout_marginBottom="@dimen/qs_media_padding" + android:visibility="gone" + app:layout_constraintVertical_bias="1" + app:layout_constraintLeft_toRightOf="@id/action0" + app:layout_constraintRight_toLeftOf="@id/action2" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintTop_toBottomOf="@id/media_seamless" /> <Constraint - android:id="@+id/actionStart" + android:id="@+id/action2" android:layout_width="48dp" android:layout_height="48dp" + android:layout_marginBottom="@dimen/qs_media_padding" android:visibility="gone" - app:layout_constraintStart_toEndOf="@id/actionNext" - app:layout_constraintEnd_toStartOf="@id/actionEnd" + app:layout_constraintVertical_bias="1" + app:layout_constraintLeft_toRightOf="@id/action1" + app:layout_constraintRight_toLeftOf="@id/action3" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintTop_toBottomOf="@id/media_seamless" /> <Constraint - android:id="@+id/actionEnd" + android:id="@+id/action3" android:layout_width="48dp" android:layout_height="48dp" + android:layout_marginBottom="@dimen/qs_media_padding" android:visibility="gone" - app:layout_constraintStart_toEndOf="@id/actionStart" - app:layout_constraintEnd_toStartOf="@id/actionPlayPause" + app:layout_constraintVertical_bias="1" + app:layout_constraintLeft_toRightOf="@id/action2" + app:layout_constraintRight_toLeftOf="@id/action4" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintTop_toBottomOf="@id/media_seamless" /> -</ConstraintSet>
\ No newline at end of file + <Constraint + android:id="@+id/action4" + android:layout_width="48dp" + android:layout_height="48dp" + android:layout_marginBottom="@dimen/qs_media_padding" + android:visibility="gone" + app:layout_constraintVertical_bias="1" + app:layout_constraintLeft_toRightOf="@id/action3" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintTop_toBottomOf="@id/media_seamless" + app:layout_constraintRight_toLeftOf="@id/media_action_barrier_end" /> +</ConstraintSet> diff --git a/packages/SystemUI/res/xml/media_session_expanded.xml b/packages/SystemUI/res/xml/media_session_expanded.xml index 18ec7aa4cab4..10da70447ec0 100644 --- a/packages/SystemUI/res/xml/media_session_expanded.xml +++ b/packages/SystemUI/res/xml/media_session_expanded.xml @@ -28,57 +28,118 @@ app:layout_constraintBottom_toBottomOf="parent" /> <Constraint + android:id="@+id/header_title" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="20dp" + android:layout_marginStart="@dimen/qs_media_padding" + android:layout_marginEnd="@dimen/qs_media_padding" + app:layout_constraintEnd_toStartOf="@id/actionPlayPause" + app:layout_constrainedWidth="true" + app:layout_constraintTop_toBottomOf="@id/icon" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintHorizontal_bias="0" /> + <Constraint + android:id="@+id/header_artist" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginEnd="@dimen/qs_media_padding" + android:layout_marginTop="0dp" + app:layout_constrainedWidth="true" + app:layout_constraintEnd_toStartOf="@id/actionPlayPause" + app:layout_constraintBottom_toTopOf="@id/media_action_barrier" + app:layout_constraintTop_toBottomOf="@id/header_title" + app:layout_constraintStart_toStartOf="@id/header_title" + app:layout_constraintVertical_bias="0" + app:layout_constraintHorizontal_bias="0" /> + + <Constraint android:id="@+id/actionPlayPause" android:layout_width="48dp" android:layout_height="48dp" + android:layout_marginStart="@dimen/qs_media_padding" android:layout_marginEnd="@dimen/qs_media_padding" + android:layout_marginBottom="0dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toBottomOf="@id/media_seamless" - app:layout_constraintBottom_toTopOf="@id/actionEnd" /> + app:layout_constraintBottom_toBottomOf="@id/header_artist" /> + <!-- + The bottom row of action buttons should remain in the same order when RTL, so their constraints + are set with right/left instead of start/end. + The chain is set to "spread" so that the progress bar can be weighted to fill any empty space. + --> <Constraint android:id="@+id/actionPrev" android:layout_width="48dp" android:layout_height="48dp" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintEnd_toStartOf="@id/media_progress_bar" + app:layout_constraintLeft_toLeftOf="parent" + app:layout_constraintRight_toLeftOf="@id/media_progress_bar" app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintTop_toBottomOf="@id/actionPlayPause" /> + app:layout_constraintTop_toBottomOf="@id/header_artist" + app:layout_constraintHorizontal_chainStyle="spread" /> <Constraint android:id="@+id/media_progress_bar" android:layout_width="0dp" - android:layout_height="wrap_content" - app:layout_constraintStart_toEndOf="@id/actionPrev" - app:layout_constraintEnd_toStartOf="@id/actionNext" + android:layout_height="48dp" + app:layout_constraintLeft_toRightOf="@id/actionPrev" + app:layout_constraintRight_toLeftOf="@id/actionNext" app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintTop_toBottomOf="@id/actionPlayPause" /> + app:layout_constraintTop_toBottomOf="@id/header_artist" + app:layout_constraintHorizontal_weight="1" /> <Constraint android:id="@+id/actionNext" android:layout_width="48dp" android:layout_height="48dp" - app:layout_constraintStart_toEndOf="@id/media_progress_bar" - app:layout_constraintEnd_toStartOf="@id/actionStart" + app:layout_constraintLeft_toRightOf="@id/media_progress_bar" + app:layout_constraintRight_toLeftOf="@id/action0" app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintTop_toBottomOf="@id/actionPlayPause" /> + app:layout_constraintTop_toBottomOf="@id/header_artist" /> <Constraint - android:id="@+id/actionStart" + android:id="@+id/action0" android:layout_width="48dp" android:layout_height="48dp" - app:layout_constraintStart_toEndOf="@id/actionNext" - app:layout_constraintEnd_toStartOf="@id/actionEnd" + app:layout_constraintLeft_toRightOf="@id/actionNext" + app:layout_constraintRight_toLeftOf="@id/action1" app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintTop_toBottomOf="@id/actionPlayPause" /> + app:layout_constraintTop_toBottomOf="@id/header_artist" /> <Constraint - android:id="@+id/actionEnd" + android:id="@+id/action1" android:layout_width="48dp" android:layout_height="48dp" - app:layout_constraintStart_toEndOf="@id/actionStart" - app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintLeft_toRightOf="@id/action0" + app:layout_constraintRight_toLeftOf="@id/action2" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintTop_toBottomOf="@id/header_artist" /> + + <Constraint + android:id="@+id/action2" + android:layout_width="48dp" + android:layout_height="48dp" + app:layout_constraintLeft_toRightOf="@id/action1" + app:layout_constraintRight_toLeftOf="@id/action3" app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintTop_toBottomOf="@id/actionPlayPause" /> + app:layout_constraintTop_toBottomOf="@id/header_artist" /> -</ConstraintSet>
\ No newline at end of file + <Constraint + android:id="@+id/action3" + android:layout_width="48dp" + android:layout_height="48dp" + app:layout_constraintLeft_toRightOf="@id/action2" + app:layout_constraintRight_toLeftOf="@id/action4" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintTop_toBottomOf="@id/header_artist" /> + + <Constraint + android:id="@+id/action4" + android:layout_width="48dp" + android:layout_height="48dp" + app:layout_constraintLeft_toRightOf="@id/action3" + app:layout_constraintRight_toRightOf="parent" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintTop_toBottomOf="@id/header_artist" /> +</ConstraintSet> diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java index 831a606e95b2..4a5b6f17af84 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java +++ b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java @@ -104,6 +104,13 @@ public class MediaControlPanel { R.id.action4 }; + // Buttons to show in small player when using semantic actions + private static final List<Integer> SEMANTIC_ACTION_IDS = List.of( + R.id.actionPlayPause, + R.id.actionPrev, + R.id.actionNext + ); + private final SeekBarViewModel mSeekBarViewModel; private SeekBarObserver mSeekBarObserver; protected final Executor mBackgroundExecutor; @@ -501,11 +508,11 @@ public class MediaControlPanel { MediaButton semanticActions = data.getSemanticActions(); actionIcons = new ArrayList<MediaAction>(); - actionIcons.add(semanticActions.getStartCustom()); + actionIcons.add(semanticActions.getCustom0()); actionIcons.add(semanticActions.getPrevOrCustom()); actionIcons.add(semanticActions.getPlayOrPause()); actionIcons.add(semanticActions.getNextOrCustom()); - actionIcons.add(semanticActions.getEndCustom()); + actionIcons.add(semanticActions.getCustom1()); actionsWhenCollapsed = new ArrayList<Integer>(); actionsWhenCollapsed.add(1); @@ -562,6 +569,9 @@ public class MediaControlPanel { /** Bind elements specific to PlayerSessionViewHolder */ private void bindSessionPlayer(@NonNull MediaData data, String key) { + ConstraintSet expandedSet = mMediaViewController.getExpandedLayout(); + ConstraintSet collapsedSet = mMediaViewController.getCollapsedLayout(); + // Default colors int surfaceColor = mBackgroundColor; int accentPrimary = com.android.settingslib.Utils.getColorAttr(mContext, @@ -660,26 +670,68 @@ public class MediaControlPanel { // Media action buttons MediaButton semanticActions = data.getSemanticActions(); + PlayerSessionViewHolder sessionHolder = (PlayerSessionViewHolder) mMediaViewHolder; + ImageButton[] genericButtons = new ImageButton[]{ + sessionHolder.getAction0(), + sessionHolder.getAction1(), + sessionHolder.getAction2(), + sessionHolder.getAction3(), + sessionHolder.getAction4()}; + + ImageButton[] semanticButtons = new ImageButton[]{ + sessionHolder.getActionPlayPause(), + sessionHolder.getActionNext(), + sessionHolder.getActionPrev()}; + if (semanticActions != null) { - PlayerSessionViewHolder sessionHolder = (PlayerSessionViewHolder) mMediaViewHolder; + // Hide all the generic buttons + for (ImageButton b: genericButtons) { + setVisibleAndAlpha(collapsedSet, b.getId(), false); + setVisibleAndAlpha(expandedSet, b.getId(), false); + } // Play/pause button has a background sessionHolder.getActionPlayPause().setBackgroundTintList(accentColorList); setSemanticButton(sessionHolder.getActionPlayPause(), semanticActions.getPlayOrPause(), - ColorStateList.valueOf(textPrimaryInverse)); + ColorStateList.valueOf(textPrimaryInverse), collapsedSet, expandedSet, true); setSemanticButton(sessionHolder.getActionNext(), semanticActions.getNextOrCustom(), - textColorList); + textColorList, collapsedSet, expandedSet, true); setSemanticButton(sessionHolder.getActionPrev(), semanticActions.getPrevOrCustom(), - textColorList); - setSemanticButton(sessionHolder.getActionStart(), semanticActions.getStartCustom(), - textColorList); - setSemanticButton(sessionHolder.getActionEnd(), semanticActions.getEndCustom(), - textColorList); + textColorList, collapsedSet, expandedSet, true); + setSemanticButton(sessionHolder.getAction0(), semanticActions.getCustom0(), + textColorList, collapsedSet, expandedSet, false); + setSemanticButton(sessionHolder.getAction1(), semanticActions.getCustom1(), + textColorList, collapsedSet, expandedSet, false); } else { - Log.w(TAG, "Using semantic player, but did not get buttons"); + // Hide all the semantic buttons + for (int id : SEMANTIC_ACTION_IDS) { + setVisibleAndAlpha(collapsedSet, id, false); + setVisibleAndAlpha(expandedSet, id, false); + } + + // Set all the generic buttons + List<Integer> actionsWhenCollapsed = data.getActionsToShowInCompact(); + List<MediaAction> actions = data.getActions(); + int i = 0; + for (; i < actions.size(); i++) { + boolean showInCompact = actionsWhenCollapsed.contains(i); + setSemanticButton(genericButtons[i], actions.get(i), textColorList, collapsedSet, + expandedSet, showInCompact); + } + for (; i < 5; i++) { + // Hide any unused buttons + setSemanticButton(genericButtons[i], null, textColorList, collapsedSet, + expandedSet, false); + } } + // If disabled, set progress bar to INVISIBLE instead of GONE so layout weights still work + boolean seekbarEnabled = mSeekBarViewModel.getEnabled(); + expandedSet.setVisibility(R.id.media_progress_bar, + seekbarEnabled ? ConstraintSet.VISIBLE : ConstraintSet.INVISIBLE); + expandedSet.setAlpha(R.id.media_progress_bar, seekbarEnabled ? 1.0f : 0.0f); + // Long press buttons mMediaViewHolder.getLongPressText().setTextColor(textColorList); mMediaViewHolder.getSettingsText().setTextColor(textColorList); @@ -692,7 +744,8 @@ public class MediaControlPanel { } private void setSemanticButton(final ImageButton button, MediaAction mediaAction, - ColorStateList fgColor) { + ColorStateList fgColor, ConstraintSet collapsedSet, ConstraintSet expandedSet, + boolean showInCompact) { button.setImageTintList(fgColor); if (mediaAction != null) { button.setImageIcon(mediaAction.getIcon()); @@ -716,6 +769,9 @@ public class MediaControlPanel { button.setContentDescription(null); button.setEnabled(false); } + + setVisibleAndAlpha(collapsedSet, button.getId(), mediaAction != null && showInCompact); + setVisibleAndAlpha(expandedSet, button.getId(), mediaAction != null); } @Nullable diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaData.kt b/packages/SystemUI/src/com/android/systemui/media/MediaData.kt index 500e82efdb0a..4cf6291fe35b 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaData.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaData.kt @@ -149,11 +149,11 @@ data class MediaButton( /** * First custom action space */ - var startCustom: MediaAction? = null, + var custom0: MediaAction? = null, /** - * Last custom action space + * Second custom action space */ - var endCustom: MediaAction? = null + var custom1: MediaAction? = null ) /** State of a media action. */ diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt index fab06c288ce1..9e14fe91f21d 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt @@ -752,8 +752,8 @@ class MediaDataManager( null } - actions.startCustom = customActions[customIdx++] - actions.endCustom = customActions[customIdx++] + actions.custom0 = customActions[customIdx++] + actions.custom1 = customActions[customIdx++] } return actions } diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaViewHolder.kt b/packages/SystemUI/src/com/android/systemui/media/MediaViewHolder.kt index e57b247da055..5f606969153c 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaViewHolder.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaViewHolder.kt @@ -60,12 +60,24 @@ abstract class MediaViewHolder constructor(itemView: View) { val settings = itemView.requireViewById<View>(R.id.settings) val settingsText = itemView.requireViewById<TextView>(R.id.settings_text) + // Action Buttons + val action0 = itemView.requireViewById<ImageButton>(R.id.action0) + val action1 = itemView.requireViewById<ImageButton>(R.id.action1) + val action2 = itemView.requireViewById<ImageButton>(R.id.action2) + val action3 = itemView.requireViewById<ImageButton>(R.id.action3) + val action4 = itemView.requireViewById<ImageButton>(R.id.action4) + init { (player.background as IlluminationDrawable).let { it.registerLightSource(seamless) it.registerLightSource(cancel) it.registerLightSource(dismiss) it.registerLightSource(settings) + it.registerLightSource(action0) + it.registerLightSource(action1) + it.registerLightSource(action2) + it.registerLightSource(action3) + it.registerLightSource(action4) } } diff --git a/packages/SystemUI/src/com/android/systemui/media/PlayerSessionViewHolder.kt b/packages/SystemUI/src/com/android/systemui/media/PlayerSessionViewHolder.kt index 87d2cffea257..6928ebb8bb32 100644 --- a/packages/SystemUI/src/com/android/systemui/media/PlayerSessionViewHolder.kt +++ b/packages/SystemUI/src/com/android/systemui/media/PlayerSessionViewHolder.kt @@ -31,16 +31,12 @@ class PlayerSessionViewHolder private constructor(itemView: View) : MediaViewHol val actionPlayPause = itemView.requireViewById<ImageButton>(R.id.actionPlayPause) val actionNext = itemView.requireViewById<ImageButton>(R.id.actionNext) val actionPrev = itemView.requireViewById<ImageButton>(R.id.actionPrev) - val actionStart = itemView.requireViewById<ImageButton>(R.id.actionStart) - val actionEnd = itemView.requireViewById<ImageButton>(R.id.actionEnd) init { (player.background as IlluminationDrawable).let { it.registerLightSource(actionPlayPause) it.registerLightSource(actionNext) it.registerLightSource(actionPrev) - it.registerLightSource(actionStart) - it.registerLightSource(actionEnd) } } @@ -49,8 +45,11 @@ class PlayerSessionViewHolder private constructor(itemView: View) : MediaViewHol R.id.actionPlayPause -> actionPlayPause R.id.actionNext -> actionNext R.id.actionPrev -> actionPrev - R.id.actionStart -> actionStart - R.id.actionEnd -> actionEnd + R.id.action0 -> action0 + R.id.action1 -> action1 + R.id.action2 -> action2 + R.id.action3 -> action3 + R.id.action4 -> action4 else -> { throw IllegalArgumentException() } @@ -90,8 +89,11 @@ class PlayerSessionViewHolder private constructor(itemView: View) : MediaViewHol R.id.actionPlayPause, R.id.actionNext, R.id.actionPrev, - R.id.actionStart, - R.id.actionEnd, + R.id.action0, + R.id.action1, + R.id.action2, + R.id.action3, + R.id.action4, R.id.icon ) val gutsIds = setOf( diff --git a/packages/SystemUI/src/com/android/systemui/media/PlayerViewHolder.kt b/packages/SystemUI/src/com/android/systemui/media/PlayerViewHolder.kt index 20b2d4a452f5..dd3fa89dea66 100644 --- a/packages/SystemUI/src/com/android/systemui/media/PlayerViewHolder.kt +++ b/packages/SystemUI/src/com/android/systemui/media/PlayerViewHolder.kt @@ -33,23 +33,6 @@ class PlayerViewHolder private constructor(itemView: View) : MediaViewHolder(ite override val elapsedTimeView = itemView.requireViewById<TextView>(R.id.media_elapsed_time) override val totalTimeView = itemView.requireViewById<TextView>(R.id.media_total_time) - // Action Buttons - val action0 = itemView.requireViewById<ImageButton>(R.id.action0) - val action1 = itemView.requireViewById<ImageButton>(R.id.action1) - val action2 = itemView.requireViewById<ImageButton>(R.id.action2) - val action3 = itemView.requireViewById<ImageButton>(R.id.action3) - val action4 = itemView.requireViewById<ImageButton>(R.id.action4) - - init { - (player.background as IlluminationDrawable).let { - it.registerLightSource(action0) - it.registerLightSource(action1) - it.registerLightSource(action2) - it.registerLightSource(action3) - it.registerLightSource(action4) - } - } - override fun getAction(id: Int): ImageButton { return when (id) { R.id.action0 -> action0 diff --git a/packages/SystemUI/src/com/android/systemui/media/SeekBarViewModel.kt b/packages/SystemUI/src/com/android/systemui/media/SeekBarViewModel.kt index 329dec24a5c3..49cd16175f0a 100644 --- a/packages/SystemUI/src/com/android/systemui/media/SeekBarViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/media/SeekBarViewModel.kt @@ -132,6 +132,8 @@ class SeekBarViewModel @Inject constructor( lateinit var logSmartspaceClick: () -> Unit + fun getEnabled() = _data.enabled + /** * Event indicating that the user has started interacting with the seek bar. */ diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt index 708fc915410c..c024087a22ea 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt @@ -59,6 +59,7 @@ import org.mockito.ArgumentMatchers.anyLong import org.mockito.Mock import org.mockito.Mockito.mock import org.mockito.Mockito.never +import org.mockito.Mockito.times import org.mockito.Mockito.verify import org.mockito.junit.MockitoJUnit import org.mockito.Mockito.`when` as whenever @@ -119,8 +120,6 @@ public class MediaControlPanelTest : SysuiTestCase() { private lateinit var actionPlayPause: ImageButton private lateinit var actionNext: ImageButton private lateinit var actionPrev: ImageButton - private lateinit var actionStart: ImageButton - private lateinit var actionEnd: ImageButton @Mock private lateinit var longPressText: TextView @Mock private lateinit var handler: Handler private lateinit var settings: View @@ -168,6 +167,17 @@ public class MediaControlPanelTest : SysuiTestCase() { cancelText = TextView(context) dismiss = FrameLayout(context) dismissText = TextView(context) + + action0 = ImageButton(context).also { it.setId(R.id.action0) } + action1 = ImageButton(context).also { it.setId(R.id.action1) } + action2 = ImageButton(context).also { it.setId(R.id.action2) } + action3 = ImageButton(context).also { it.setId(R.id.action3) } + action4 = ImageButton(context).also { it.setId(R.id.action4) } + + actionPlayPause = ImageButton(context).also { it.setId(R.id.actionPlayPause) } + actionPrev = ImageButton(context).also { it.setId(R.id.actionPrev) } + actionNext = ImageButton(context).also { it.setId(R.id.actionNext) } + initPlayerHolderMocks() initSessionHolderMocks() @@ -208,90 +218,64 @@ public class MediaControlPanelTest : SysuiTestCase() { whenever(mediaFlags.useMediaSessionLayout()).thenReturn(false) } - /** Mock view holder for the notification player */ - private fun initPlayerHolderMocks() { - whenever(holder.player).thenReturn(view) - whenever(holder.appIcon).thenReturn(appIcon) - whenever(holder.albumView).thenReturn(albumView) - whenever(holder.titleText).thenReturn(titleText) - whenever(holder.artistText).thenReturn(artistText) + /** + * Initialize elements common to both view holders + */ + private fun initMediaViewHolderMocks(viewHolder: MediaViewHolder) { + whenever(viewHolder.player).thenReturn(view) + whenever(viewHolder.appIcon).thenReturn(appIcon) + whenever(viewHolder.albumView).thenReturn(albumView) + whenever(viewHolder.titleText).thenReturn(titleText) + whenever(viewHolder.artistText).thenReturn(artistText) whenever(seamlessBackground.getDrawable(0)).thenReturn(mock(GradientDrawable::class.java)) - whenever(holder.seamless).thenReturn(seamless) - whenever(holder.seamlessButton).thenReturn(seamlessButton) - whenever(holder.seamlessIcon).thenReturn(seamlessIcon) - whenever(holder.seamlessText).thenReturn(seamlessText) - whenever(holder.seekBar).thenReturn(seekBar) - whenever(holder.elapsedTimeView).thenReturn(elapsedTimeView) - whenever(holder.totalTimeView).thenReturn(totalTimeView) + whenever(viewHolder.seamless).thenReturn(seamless) + whenever(viewHolder.seamlessButton).thenReturn(seamlessButton) + whenever(viewHolder.seamlessIcon).thenReturn(seamlessIcon) + whenever(viewHolder.seamlessText).thenReturn(seamlessText) + whenever(viewHolder.seekBar).thenReturn(seekBar) // Action buttons - action0 = ImageButton(context) - whenever(holder.action0).thenReturn(action0) - whenever(holder.getAction(R.id.action0)).thenReturn(action0) - action1 = ImageButton(context) - whenever(holder.action1).thenReturn(action1) - whenever(holder.getAction(R.id.action1)).thenReturn(action1) - action2 = ImageButton(context) - whenever(holder.action2).thenReturn(action2) - whenever(holder.getAction(R.id.action2)).thenReturn(action2) - action3 = ImageButton(context) - whenever(holder.action3).thenReturn(action3) - whenever(holder.getAction(R.id.action3)).thenReturn(action3) - action4 = ImageButton(context) - whenever(holder.action4).thenReturn(action4) - whenever(holder.getAction(R.id.action4)).thenReturn(action4) + whenever(viewHolder.action0).thenReturn(action0) + whenever(viewHolder.getAction(R.id.action0)).thenReturn(action0) + whenever(viewHolder.action1).thenReturn(action1) + whenever(viewHolder.getAction(R.id.action1)).thenReturn(action1) + whenever(viewHolder.action2).thenReturn(action2) + whenever(viewHolder.getAction(R.id.action2)).thenReturn(action2) + whenever(viewHolder.action3).thenReturn(action3) + whenever(viewHolder.getAction(R.id.action3)).thenReturn(action3) + whenever(viewHolder.action4).thenReturn(action4) + whenever(viewHolder.getAction(R.id.action4)).thenReturn(action4) // Long press menu - whenever(holder.longPressText).thenReturn(longPressText) + whenever(viewHolder.longPressText).thenReturn(longPressText) whenever(longPressText.handler).thenReturn(handler) - whenever(holder.settings).thenReturn(settings) - whenever(holder.settingsText).thenReturn(settingsText) - whenever(holder.cancel).thenReturn(cancel) - whenever(holder.cancelText).thenReturn(cancelText) - whenever(holder.dismiss).thenReturn(dismiss) - whenever(holder.dismissText).thenReturn(dismissText) + whenever(viewHolder.settings).thenReturn(settings) + whenever(viewHolder.settingsText).thenReturn(settingsText) + whenever(viewHolder.cancel).thenReturn(cancel) + whenever(viewHolder.cancelText).thenReturn(cancelText) + whenever(viewHolder.dismiss).thenReturn(dismiss) + whenever(viewHolder.dismissText).thenReturn(dismissText) + } + + /** Mock view holder for the notification player */ + private fun initPlayerHolderMocks() { + initMediaViewHolderMocks(holder) + + whenever(holder.elapsedTimeView).thenReturn(elapsedTimeView) + whenever(holder.totalTimeView).thenReturn(totalTimeView) } /** Mock view holder for session player */ private fun initSessionHolderMocks() { - whenever(sessionHolder.player).thenReturn(view) - whenever(sessionHolder.albumView).thenReturn(albumView) - whenever(sessionHolder.appIcon).thenReturn(appIcon) - whenever(sessionHolder.titleText).thenReturn(titleText) - whenever(sessionHolder.artistText).thenReturn(artistText) - val seamlessBackground = mock(RippleDrawable::class.java) - whenever(seamlessBackground.getDrawable(0)).thenReturn(mock(GradientDrawable::class.java)) - whenever(sessionHolder.seamless).thenReturn(seamless) - whenever(sessionHolder.seamlessButton).thenReturn(seamlessButton) - whenever(sessionHolder.seamlessIcon).thenReturn(seamlessIcon) - whenever(sessionHolder.seamlessText).thenReturn(seamlessText) - whenever(sessionHolder.seekBar).thenReturn(seekBar) + initMediaViewHolderMocks(sessionHolder) - // Action buttons - actionPlayPause = ImageButton(context) + // Semantic action buttons whenever(sessionHolder.actionPlayPause).thenReturn(actionPlayPause) whenever(sessionHolder.getAction(R.id.actionPlayPause)).thenReturn(actionPlayPause) - actionNext = ImageButton(context) whenever(sessionHolder.actionNext).thenReturn(actionNext) whenever(sessionHolder.getAction(R.id.actionNext)).thenReturn(actionNext) - actionPrev = ImageButton(context) whenever(sessionHolder.actionPrev).thenReturn(actionPrev) whenever(sessionHolder.getAction(R.id.actionPrev)).thenReturn(actionPrev) - actionStart = ImageButton(context) - whenever(sessionHolder.actionStart).thenReturn(actionStart) - whenever(sessionHolder.getAction(R.id.actionStart)).thenReturn(actionStart) - actionEnd = ImageButton(context) - whenever(sessionHolder.actionEnd).thenReturn(actionEnd) - whenever(sessionHolder.getAction(R.id.actionEnd)).thenReturn(actionEnd) - - // Long press menu - whenever(sessionHolder.longPressText).thenReturn(longPressText) - whenever(sessionHolder.settings).thenReturn(settings) - whenever(sessionHolder.settingsText).thenReturn(settingsText) - whenever(sessionHolder.cancel).thenReturn(cancel) - whenever(sessionHolder.cancelText).thenReturn(cancelText) - whenever(sessionHolder.dismiss).thenReturn(dismiss) - whenever(sessionHolder.dismissText).thenReturn(dismissText) } @After @@ -316,8 +300,8 @@ public class MediaControlPanelTest : SysuiTestCase() { val semanticActions = MediaButton( playOrPause = MediaAction(icon, Runnable {}, "play"), nextOrCustom = MediaAction(icon, Runnable {}, "next"), - startCustom = MediaAction(icon, null, "custom 1"), - endCustom = MediaAction(icon, null, "custom 2") + custom0 = MediaAction(icon, null, "custom 0"), + custom1 = MediaAction(icon, null, "custom 1") ) val state = mediaData.copy(semanticActions = semanticActions) @@ -325,7 +309,7 @@ public class MediaControlPanelTest : SysuiTestCase() { player.bindPlayer(state, PACKAGE) verify(expandedSet).setVisibility(R.id.action0, ConstraintSet.VISIBLE) - assertThat(action0.contentDescription).isEqualTo("custom 1") + assertThat(action0.contentDescription).isEqualTo("custom 0") assertThat(action0.isEnabled()).isFalse() verify(expandedSet).setVisibility(R.id.action1, ConstraintSet.INVISIBLE) @@ -340,7 +324,7 @@ public class MediaControlPanelTest : SysuiTestCase() { assertThat(action3.contentDescription).isEqualTo("next") verify(expandedSet).setVisibility(R.id.action4, ConstraintSet.VISIBLE) - assertThat(action4.contentDescription).isEqualTo("custom 2") + assertThat(action4.contentDescription).isEqualTo("custom 1") assertThat(action4.isEnabled()).isFalse() } @@ -353,28 +337,96 @@ public class MediaControlPanelTest : SysuiTestCase() { val semanticActions = MediaButton( playOrPause = MediaAction(icon, Runnable {}, "play"), nextOrCustom = MediaAction(icon, Runnable {}, "next"), - startCustom = MediaAction(icon, null, "custom 1"), - endCustom = MediaAction(icon, null, "custom 2") + custom0 = MediaAction(icon, null, "custom 0"), + custom1 = MediaAction(icon, null, "custom 1") ) val state = mediaData.copy(semanticActions = semanticActions) player.attachPlayer(sessionHolder, MediaViewController.TYPE.PLAYER_SESSION) player.bindPlayer(state, PACKAGE) - assertThat(actionStart.contentDescription).isEqualTo("custom 1") - assertThat(actionStart.isEnabled()).isFalse() - assertThat(actionPrev.isEnabled()).isFalse() assertThat(actionPrev.drawable).isNull() + verify(collapsedSet).setVisibility(R.id.actionPrev, ConstraintSet.GONE) assertThat(actionPlayPause.isEnabled()).isTrue() assertThat(actionPlayPause.contentDescription).isEqualTo("play") + verify(collapsedSet).setVisibility(R.id.actionPlayPause, ConstraintSet.VISIBLE) assertThat(actionNext.isEnabled()).isTrue() assertThat(actionNext.contentDescription).isEqualTo("next") + verify(collapsedSet).setVisibility(R.id.actionNext, ConstraintSet.VISIBLE) + + // Called twice since these IDs are used as generic buttons + assertThat(action0.contentDescription).isEqualTo("custom 0") + assertThat(action0.isEnabled()).isFalse() + verify(collapsedSet, times(2)).setVisibility(R.id.action0, ConstraintSet.GONE) + + assertThat(action1.contentDescription).isEqualTo("custom 1") + assertThat(action1.isEnabled()).isFalse() + verify(collapsedSet, times(2)).setVisibility(R.id.action1, ConstraintSet.GONE) + + // Verify generic buttons are hidden + verify(collapsedSet).setVisibility(R.id.action2, ConstraintSet.GONE) + verify(expandedSet).setVisibility(R.id.action2, ConstraintSet.GONE) + + verify(collapsedSet).setVisibility(R.id.action3, ConstraintSet.GONE) + verify(expandedSet).setVisibility(R.id.action3, ConstraintSet.GONE) + + verify(collapsedSet).setVisibility(R.id.action4, ConstraintSet.GONE) + verify(expandedSet).setVisibility(R.id.action4, ConstraintSet.GONE) + } + + @Test + fun bindNotificationActionsNewLayout() { + whenever(mediaFlags.areMediaSessionActionsEnabled()).thenReturn(true) + whenever(mediaFlags.useMediaSessionLayout()).thenReturn(true) + + val icon = Icon.createWithResource(context, android.R.drawable.ic_media_play) + val actions = listOf( + MediaAction(icon, Runnable {}, "previous"), + MediaAction(icon, Runnable {}, "play"), + MediaAction(icon, null, "next"), + MediaAction(icon, null, "custom 0"), + MediaAction(icon, Runnable {}, "custom 1") + ) + val state = mediaData.copy(actions = actions, + actionsToShowInCompact = listOf(1, 2), + semanticActions = null) + + player.attachPlayer(sessionHolder, MediaViewController.TYPE.PLAYER_SESSION) + player.bindPlayer(state, PACKAGE) + + // Verify semantic actions are hidden + verify(collapsedSet).setVisibility(R.id.actionPrev, ConstraintSet.GONE) + verify(expandedSet).setVisibility(R.id.actionPrev, ConstraintSet.GONE) + + verify(collapsedSet).setVisibility(R.id.actionPlayPause, ConstraintSet.GONE) + verify(expandedSet).setVisibility(R.id.actionPlayPause, ConstraintSet.GONE) + + verify(collapsedSet).setVisibility(R.id.actionNext, ConstraintSet.GONE) + verify(expandedSet).setVisibility(R.id.actionNext, ConstraintSet.GONE) + + // Generic actions all enabled + assertThat(action0.contentDescription).isEqualTo("previous") + assertThat(action0.isEnabled()).isTrue() + verify(collapsedSet).setVisibility(R.id.action0, ConstraintSet.GONE) + + assertThat(action1.contentDescription).isEqualTo("play") + assertThat(action1.isEnabled()).isTrue() + verify(collapsedSet).setVisibility(R.id.action1, ConstraintSet.VISIBLE) + + assertThat(action2.contentDescription).isEqualTo("next") + assertThat(action2.isEnabled()).isFalse() + verify(collapsedSet).setVisibility(R.id.action2, ConstraintSet.VISIBLE) + + assertThat(action3.contentDescription).isEqualTo("custom 0") + assertThat(action3.isEnabled()).isFalse() + verify(collapsedSet).setVisibility(R.id.action3, ConstraintSet.GONE) - assertThat(actionEnd.contentDescription).isEqualTo("custom 2") - assertThat(actionEnd.isEnabled()).isFalse() + assertThat(action4.contentDescription).isEqualTo("custom 1") + assertThat(action4.isEnabled()).isTrue() + verify(collapsedSet).setVisibility(R.id.action4, ConstraintSet.GONE) } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt index 021f70e05b32..925ae30e8773 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt @@ -659,11 +659,11 @@ class MediaDataManagerTest : SysuiTestCase() { actions.nextOrCustom!!.action!!.run() verify(transportControls).skipToNext() - assertThat(actions.startCustom).isNotNull() - assertThat(actions.startCustom!!.contentDescription).isEqualTo(customDesc[0]) + assertThat(actions.custom0).isNotNull() + assertThat(actions.custom0!!.contentDescription).isEqualTo(customDesc[0]) - assertThat(actions.endCustom).isNotNull() - assertThat(actions.endCustom!!.contentDescription).isEqualTo(customDesc[1]) + assertThat(actions.custom1).isNotNull() + assertThat(actions.custom1!!.contentDescription).isEqualTo(customDesc[1]) } @Test @@ -697,11 +697,11 @@ class MediaDataManagerTest : SysuiTestCase() { assertThat(actions.nextOrCustom).isNotNull() assertThat(actions.nextOrCustom!!.contentDescription).isEqualTo(customDesc[1]) - assertThat(actions.startCustom).isNotNull() - assertThat(actions.startCustom!!.contentDescription).isEqualTo(customDesc[2]) + assertThat(actions.custom0).isNotNull() + assertThat(actions.custom0!!.contentDescription).isEqualTo(customDesc[2]) - assertThat(actions.endCustom).isNotNull() - assertThat(actions.endCustom!!.contentDescription).isEqualTo(customDesc[3]) + assertThat(actions.custom1).isNotNull() + assertThat(actions.custom1!!.contentDescription).isEqualTo(customDesc[3]) } @Test @@ -737,10 +737,10 @@ class MediaDataManagerTest : SysuiTestCase() { assertThat(actions.prevOrCustom).isNull() assertThat(actions.nextOrCustom).isNull() - assertThat(actions.startCustom).isNotNull() - assertThat(actions.startCustom!!.contentDescription).isEqualTo(customDesc[0]) + assertThat(actions.custom0).isNotNull() + assertThat(actions.custom0!!.contentDescription).isEqualTo(customDesc[0]) - assertThat(actions.endCustom).isNotNull() - assertThat(actions.endCustom!!.contentDescription).isEqualTo(customDesc[1]) + assertThat(actions.custom1).isNotNull() + assertThat(actions.custom1!!.contentDescription).isEqualTo(customDesc[1]) } } |