Loading packages/SystemUI/src/com/android/systemui/flags/Flags.java +2 −1 Original line number Diff line number Diff line Loading @@ -128,7 +128,8 @@ public class Flags { /***************************************/ // 900 - media public static final BooleanFlag MEDIA_TAP_TO_TRANSFER = new BooleanFlag(900, false); public static final BooleanFlag MEDIA_SESSION_ACTIONS = new BooleanFlag(901, false); public static final BooleanFlag MEDIA_SESSION_ACTIONS = new BooleanFlag(901, true); public static final BooleanFlag MEDIA_SESSION_LAYOUT = new BooleanFlag(902, false); // Pay no attention to the reflection behind the curtain. // ========================== Curtain ========================== Loading packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt +1 −1 Original line number Diff line number Diff line Loading @@ -418,7 +418,7 @@ class MediaCarouselController @Inject constructor( .elementAtOrNull(mediaCarouselScrollHandler.visibleMediaIndex) if (existingPlayer == null) { var newPlayer = mediaControlPanelFactory.get() if (mediaFlags.areMediaSessionActionsEnabled()) { if (mediaFlags.useMediaSessionLayout()) { newPlayer.attachPlayer( PlayerSessionViewHolder.create(LayoutInflater.from(context), mediaContent), MediaViewController.TYPE.PLAYER_SESSION) Loading packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java +19 −0 Original line number Diff line number Diff line Loading @@ -61,6 +61,7 @@ import com.android.systemui.util.animation.TransitionLayout; import com.android.systemui.util.time.SystemClock; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Executor; Loading Loading @@ -480,6 +481,24 @@ public class MediaControlPanel { List<MediaAction> actionIcons = data.getActions(); List<Integer> actionsWhenCollapsed = data.getActionsToShowInCompact(); // If the session actions flag is enabled, but we're still using the regular layout, use // the session actions anyways if (mMediaFlags.areMediaSessionActionsEnabled() && data.getSemanticActions() != null) { MediaButton semanticActions = data.getSemanticActions(); actionIcons = new ArrayList<MediaAction>(); actionIcons.add(semanticActions.getStartCustom()); actionIcons.add(semanticActions.getPrevOrCustom()); actionIcons.add(semanticActions.getPlayOrPause()); actionIcons.add(semanticActions.getNextOrCustom()); actionIcons.add(semanticActions.getEndCustom()); actionsWhenCollapsed = new ArrayList<Integer>(); actionsWhenCollapsed.add(1); actionsWhenCollapsed.add(2); actionsWhenCollapsed.add(3); } int i = 0; for (; i < actionIcons.size() && i < ACTION_IDS.length; i++) { int actionId = ACTION_IDS[i]; Loading packages/SystemUI/src/com/android/systemui/media/MediaFlags.kt +8 −0 Original line number Diff line number Diff line Loading @@ -29,4 +29,12 @@ class MediaFlags @Inject constructor(private val featureFlags: FeatureFlags) { fun areMediaSessionActionsEnabled(): Boolean { return featureFlags.isEnabled(Flags.MEDIA_SESSION_ACTIONS) } /** * Check whether media controls should use the new session-based layout */ fun useMediaSessionLayout(): Boolean { return featureFlags.isEnabled(Flags.MEDIA_SESSION_ACTIONS) && featureFlags.isEnabled(Flags.MEDIA_SESSION_LAYOUT) } } No newline at end of file packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt +41 −1 Original line number Diff line number Diff line Loading @@ -202,6 +202,7 @@ public class MediaControlPanelTest : SysuiTestCase() { resumeAction = null) whenever(mediaFlags.areMediaSessionActionsEnabled()).thenReturn(false) whenever(mediaFlags.useMediaSessionLayout()).thenReturn(false) } /** Mock view holder for the notification player */ Loading Loading @@ -301,8 +302,47 @@ public class MediaControlPanelTest : SysuiTestCase() { } @Test fun bindSemanticActions() { fun bindSemanticActionsOldLayout() { whenever(mediaFlags.areMediaSessionActionsEnabled()).thenReturn(true) whenever(mediaFlags.useMediaSessionLayout()).thenReturn(false) val icon = Icon.createWithResource(context, android.R.drawable.ic_media_play) 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") ) val state = mediaData.copy(semanticActions = semanticActions) player.attachPlayer(holder, MediaViewController.TYPE.PLAYER) player.bindPlayer(state, PACKAGE) verify(expandedSet).setVisibility(R.id.action0, ConstraintSet.VISIBLE) assertThat(action0.contentDescription).isEqualTo("custom 1") assertThat(action0.isEnabled()).isFalse() verify(expandedSet).setVisibility(R.id.action1, ConstraintSet.INVISIBLE) assertThat(action1.isEnabled()).isFalse() verify(expandedSet).setVisibility(R.id.action2, ConstraintSet.VISIBLE) assertThat(action2.isEnabled()).isTrue() assertThat(action2.contentDescription).isEqualTo("play") verify(expandedSet).setVisibility(R.id.action3, ConstraintSet.VISIBLE) assertThat(action3.isEnabled()).isTrue() assertThat(action3.contentDescription).isEqualTo("next") verify(expandedSet).setVisibility(R.id.action4, ConstraintSet.VISIBLE) assertThat(action4.contentDescription).isEqualTo("custom 2") assertThat(action4.isEnabled()).isFalse() } @Test fun bindSemanticActionsNewLayout() { whenever(mediaFlags.areMediaSessionActionsEnabled()).thenReturn(true) whenever(mediaFlags.useMediaSessionLayout()).thenReturn(true) val icon = Icon.createWithResource(context, android.R.drawable.ic_media_play) val semanticActions = MediaButton( playOrPause = MediaAction(icon, Runnable {}, "play"), Loading Loading
packages/SystemUI/src/com/android/systemui/flags/Flags.java +2 −1 Original line number Diff line number Diff line Loading @@ -128,7 +128,8 @@ public class Flags { /***************************************/ // 900 - media public static final BooleanFlag MEDIA_TAP_TO_TRANSFER = new BooleanFlag(900, false); public static final BooleanFlag MEDIA_SESSION_ACTIONS = new BooleanFlag(901, false); public static final BooleanFlag MEDIA_SESSION_ACTIONS = new BooleanFlag(901, true); public static final BooleanFlag MEDIA_SESSION_LAYOUT = new BooleanFlag(902, false); // Pay no attention to the reflection behind the curtain. // ========================== Curtain ========================== Loading
packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt +1 −1 Original line number Diff line number Diff line Loading @@ -418,7 +418,7 @@ class MediaCarouselController @Inject constructor( .elementAtOrNull(mediaCarouselScrollHandler.visibleMediaIndex) if (existingPlayer == null) { var newPlayer = mediaControlPanelFactory.get() if (mediaFlags.areMediaSessionActionsEnabled()) { if (mediaFlags.useMediaSessionLayout()) { newPlayer.attachPlayer( PlayerSessionViewHolder.create(LayoutInflater.from(context), mediaContent), MediaViewController.TYPE.PLAYER_SESSION) Loading
packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java +19 −0 Original line number Diff line number Diff line Loading @@ -61,6 +61,7 @@ import com.android.systemui.util.animation.TransitionLayout; import com.android.systemui.util.time.SystemClock; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Executor; Loading Loading @@ -480,6 +481,24 @@ public class MediaControlPanel { List<MediaAction> actionIcons = data.getActions(); List<Integer> actionsWhenCollapsed = data.getActionsToShowInCompact(); // If the session actions flag is enabled, but we're still using the regular layout, use // the session actions anyways if (mMediaFlags.areMediaSessionActionsEnabled() && data.getSemanticActions() != null) { MediaButton semanticActions = data.getSemanticActions(); actionIcons = new ArrayList<MediaAction>(); actionIcons.add(semanticActions.getStartCustom()); actionIcons.add(semanticActions.getPrevOrCustom()); actionIcons.add(semanticActions.getPlayOrPause()); actionIcons.add(semanticActions.getNextOrCustom()); actionIcons.add(semanticActions.getEndCustom()); actionsWhenCollapsed = new ArrayList<Integer>(); actionsWhenCollapsed.add(1); actionsWhenCollapsed.add(2); actionsWhenCollapsed.add(3); } int i = 0; for (; i < actionIcons.size() && i < ACTION_IDS.length; i++) { int actionId = ACTION_IDS[i]; Loading
packages/SystemUI/src/com/android/systemui/media/MediaFlags.kt +8 −0 Original line number Diff line number Diff line Loading @@ -29,4 +29,12 @@ class MediaFlags @Inject constructor(private val featureFlags: FeatureFlags) { fun areMediaSessionActionsEnabled(): Boolean { return featureFlags.isEnabled(Flags.MEDIA_SESSION_ACTIONS) } /** * Check whether media controls should use the new session-based layout */ fun useMediaSessionLayout(): Boolean { return featureFlags.isEnabled(Flags.MEDIA_SESSION_ACTIONS) && featureFlags.isEnabled(Flags.MEDIA_SESSION_LAYOUT) } } No newline at end of file
packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt +41 −1 Original line number Diff line number Diff line Loading @@ -202,6 +202,7 @@ public class MediaControlPanelTest : SysuiTestCase() { resumeAction = null) whenever(mediaFlags.areMediaSessionActionsEnabled()).thenReturn(false) whenever(mediaFlags.useMediaSessionLayout()).thenReturn(false) } /** Mock view holder for the notification player */ Loading Loading @@ -301,8 +302,47 @@ public class MediaControlPanelTest : SysuiTestCase() { } @Test fun bindSemanticActions() { fun bindSemanticActionsOldLayout() { whenever(mediaFlags.areMediaSessionActionsEnabled()).thenReturn(true) whenever(mediaFlags.useMediaSessionLayout()).thenReturn(false) val icon = Icon.createWithResource(context, android.R.drawable.ic_media_play) 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") ) val state = mediaData.copy(semanticActions = semanticActions) player.attachPlayer(holder, MediaViewController.TYPE.PLAYER) player.bindPlayer(state, PACKAGE) verify(expandedSet).setVisibility(R.id.action0, ConstraintSet.VISIBLE) assertThat(action0.contentDescription).isEqualTo("custom 1") assertThat(action0.isEnabled()).isFalse() verify(expandedSet).setVisibility(R.id.action1, ConstraintSet.INVISIBLE) assertThat(action1.isEnabled()).isFalse() verify(expandedSet).setVisibility(R.id.action2, ConstraintSet.VISIBLE) assertThat(action2.isEnabled()).isTrue() assertThat(action2.contentDescription).isEqualTo("play") verify(expandedSet).setVisibility(R.id.action3, ConstraintSet.VISIBLE) assertThat(action3.isEnabled()).isTrue() assertThat(action3.contentDescription).isEqualTo("next") verify(expandedSet).setVisibility(R.id.action4, ConstraintSet.VISIBLE) assertThat(action4.contentDescription).isEqualTo("custom 2") assertThat(action4.isEnabled()).isFalse() } @Test fun bindSemanticActionsNewLayout() { whenever(mediaFlags.areMediaSessionActionsEnabled()).thenReturn(true) whenever(mediaFlags.useMediaSessionLayout()).thenReturn(true) val icon = Icon.createWithResource(context, android.R.drawable.ic_media_play) val semanticActions = MediaButton( playOrPause = MediaAction(icon, Runnable {}, "play"), Loading