Loading packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java +9 −10 Original line number Diff line number Diff line Loading @@ -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(); Loading @@ -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, Loading packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt +9 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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) Loading packages/SystemUI/src/com/android/systemui/media/MediaViewHolder.kt +9 −0 Original line number Diff line number Diff line Loading @@ -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 packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt +31 −0 Original line number Diff line number Diff line package com.android.systemui.media import android.app.Notification import android.app.Notification.MediaStyle import android.app.PendingIntent import android.app.smartspace.SmartspaceAction Loading Loading @@ -620,6 +621,36 @@ class MediaDataManagerTest : SysuiTestCase() { MediaDataManager.MAX_COMPACT_ACTIONS) } @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" Loading Loading
packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java +9 −10 Original line number Diff line number Diff line Loading @@ -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(); Loading @@ -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, Loading
packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt +9 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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) Loading
packages/SystemUI/src/com/android/systemui/media/MediaViewHolder.kt +9 −0 Original line number Diff line number Diff line Loading @@ -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
packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt +31 −0 Original line number Diff line number Diff line package com.android.systemui.media import android.app.Notification import android.app.Notification.MediaStyle import android.app.PendingIntent import android.app.smartspace.SmartspaceAction Loading Loading @@ -620,6 +621,36 @@ class MediaDataManagerTest : SysuiTestCase() { MediaDataManager.MAX_COMPACT_ACTIONS) } @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" Loading