diff options
4 files changed, 58 insertions, 10 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java index d37f3ae67fae..547d13ce309a 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java +++ b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java @@ -611,12 +611,11 @@ public class MediaControlPanel { private void bindActionButtons(MediaData data) { MediaButton semanticActions = data.getSemanticActions(); - ImageButton[] genericButtons = new ImageButton[]{ - mMediaViewHolder.getAction0(), - mMediaViewHolder.getAction1(), - mMediaViewHolder.getAction2(), - mMediaViewHolder.getAction3(), - mMediaViewHolder.getAction4()}; + + List<ImageButton> genericButtons = new ArrayList<>(); + for (int id : MediaViewHolder.Companion.getGenericButtonIds()) { + genericButtons.add(mMediaViewHolder.getAction(id)); + } ConstraintSet expandedSet = mMediaViewController.getExpandedLayout(); ConstraintSet collapsedSet = mMediaViewController.getCollapsedLayout(); @@ -643,19 +642,19 @@ public class MediaControlPanel { List<Integer> actionsWhenCollapsed = data.getActionsToShowInCompact(); List<MediaAction> actions = data.getActions(); int i = 0; - for (; i < actions.size(); i++) { + for (; i < actions.size() && i < genericButtons.size(); i++) { boolean showInCompact = actionsWhenCollapsed.contains(i); setGenericButton( - genericButtons[i], + genericButtons.get(i), actions.get(i), collapsedSet, expandedSet, showInCompact); } - for (; i < 5; i++) { + for (; i < genericButtons.size(); i++) { // Hide any unused buttons setGenericButton( - genericButtons[i], + genericButtons.get(i), /* mediaAction= */ null, collapsedSet, expandedSet, diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt index 84e6f7aafc6f..9a2977d56153 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt @@ -161,6 +161,10 @@ class MediaDataManager( @JvmField val MAX_COMPACT_ACTIONS = 3 + // Maximum number of actions allowed in expanded view + @JvmField + val MAX_NOTIFICATION_ACTIONS = MediaViewHolder.genericButtonIds.size + /** Maximum number of [PlaybackState.CustomAction] buttons supported */ @JvmField val MAX_CUSTOM_ACTIONS = 4 @@ -727,6 +731,11 @@ class MediaDataManager( if (actions != null) { for ((index, action) in actions.withIndex()) { + if (index == MAX_NOTIFICATION_ACTIONS) { + Log.w(TAG, "Too many notification actions for ${sbn.key}," + + " limiting to first $MAX_NOTIFICATION_ACTIONS") + break + } if (action.getIcon() == null) { if (DEBUG) Log.i(TAG, "No icon for action $index ${action.title}") actionsToShowCollapsed.remove(index) diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaViewHolder.kt b/packages/SystemUI/src/com/android/systemui/media/MediaViewHolder.kt index 34a77f26122c..8964d7114e74 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaViewHolder.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaViewHolder.kt @@ -178,5 +178,14 @@ class MediaViewHolder constructor(itemView: View) { R.id.dismiss, R.id.settings ) + + // Buttons used for notification-based actions + val genericButtonIds = setOf( + R.id.action0, + R.id.action1, + R.id.action2, + R.id.action3, + R.id.action4 + ) } }
\ No newline at end of file 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 b84737d4ce13..68eebede1482 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt @@ -1,5 +1,6 @@ package com.android.systemui.media +import android.app.Notification import android.app.Notification.MediaStyle import android.app.PendingIntent import android.app.smartspace.SmartspaceAction @@ -621,6 +622,36 @@ class MediaDataManagerTest : SysuiTestCase() { } @Test + fun testTooManyNotificationActions_isTruncated() { + // GIVEN a notification where too many notification actions are added + val action = Notification.Action(R.drawable.ic_android, "action", null) + val notif = SbnBuilder().run { + setPkg(PACKAGE_NAME) + modifyNotification(context).also { + it.setSmallIcon(android.R.drawable.ic_media_pause) + it.setStyle(MediaStyle().apply { + setMediaSession(session.sessionToken) + }) + for (i in 0..MediaDataManager.MAX_NOTIFICATION_ACTIONS) { + it.addAction(action) + } + } + build() + } + + // WHEN the notification is loaded + mediaDataManager.onNotificationAdded(KEY, notif) + assertThat(backgroundExecutor.runAllReady()).isEqualTo(1) + assertThat(foregroundExecutor.runAllReady()).isEqualTo(1) + + // THEN only the first MAX_NOTIFICATION_ACTIONS are actually included + verify(listener).onMediaDataLoaded(eq(KEY), eq(null), capture(mediaDataCaptor), eq(true), + eq(0), eq(false)) + assertThat(mediaDataCaptor.value.actions.size).isEqualTo( + MediaDataManager.MAX_NOTIFICATION_ACTIONS) + } + + @Test fun testPlaybackActions_noState_usesNotification() { val desc = "Notification Action" whenever(mediaFlags.areMediaSessionActionsEnabled(any(), any())).thenReturn(true) |