Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0b7a91d2 authored by Beth Thibodeau's avatar Beth Thibodeau Committed by Android (Google) Code Review
Browse files

Merge "Add flag to use PlaybackState actions in media controls"

parents 81fae702 bbe92d44
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -2164,6 +2164,15 @@
    <!-- Content description for media cotnrols progress bar [CHAR_LIMIT=NONE] -->
    <string name="controls_media_seekbar_description"><xliff:g id="elapsed_time" example="1:30">%1$s</xliff:g> of <xliff:g id="total_time" example="3:00">%2$s</xliff:g></string>

    <!-- Description for button in media controls. Pressing button starts playback [CHAR_LIMIT=NONE] -->
    <string name="controls_media_button_play">Play</string>
    <!-- Description for button in media controls. Pressing button pauses playback [CHAR_LIMIT=NONE] -->
    <string name="controls_media_button_pause">Pause</string>
    <!-- Description for button in media controls. Pressing button goes to previous track [CHAR_LIMIT=NONE] -->
    <string name="controls_media_button_prev">Previous track</string>
    <!-- Description for button in media controls. Pressing button goes to next track [CHAR_LIMIT=NONE] -->
    <string name="controls_media_button_next">Next track</string>

    <!-- Title for Smartspace recommendation card within media controls. The "Play" means the action to play a media [CHAR_LIMIT=10] -->
    <string name="controls_media_smartspace_rec_title">Play</string>
    <!-- Description for Smartspace recommendation card within media controls [CHAR_LIMIT=NONE] -->
+1 −0
Original line number Diff line number Diff line
@@ -121,6 +121,7 @@ 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);

    // Pay no attention to the reflection behind the curtain.
    // ========================== Curtain ==========================
+17 −2
Original line number Diff line number Diff line
@@ -862,8 +862,23 @@ class MediaCarouselController @Inject constructor(

@VisibleForTesting
internal object MediaPlayerData {
    private val EMPTY = MediaData(-1, false, 0, null, null, null, null, null,
            emptyList(), emptyList(), "INVALID", null, null, null, true, null)
    private val EMPTY = MediaData(
            userId = -1,
            initialized = false,
            backgroundColor = 0,
            app = null,
            appIcon = null,
            artist = null,
            song = null,
            artwork = null,
            actions = emptyList(),
            actionsToShowInCompact = emptyList(),
            packageName = "INVALID",
            token = null,
            clickIntent = null,
            device = null,
            active = true,
            resumeAction = null)
    // Whether should prioritize Smartspace card.
    internal var shouldPrioritizeSs: Boolean = false
        private set
+52 −21
Original line number Diff line number Diff line
@@ -62,6 +62,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;

@@ -122,6 +123,8 @@ public class MediaControlPanel {
    private MediaCarouselController mMediaCarouselController;
    private final MediaOutputDialogFactory mMediaOutputDialogFactory;
    private final FalsingManager mFalsingManager;
    private final MediaFlags mMediaFlags;

    // Used for swipe-to-dismiss logging.
    protected boolean mIsImpressed = false;
    private SystemClock mSystemClock;
@@ -138,7 +141,7 @@ public class MediaControlPanel {
            SeekBarViewModel seekBarViewModel, Lazy<MediaDataManager> lazyMediaDataManager,
            KeyguardDismissUtil keyguardDismissUtil, MediaOutputDialogFactory
            mediaOutputDialogFactory, MediaCarouselController mediaCarouselController,
            FalsingManager falsingManager, SystemClock systemClock) {
            FalsingManager falsingManager, MediaFlags mediaFlags, SystemClock systemClock) {
        mContext = context;
        mBackgroundExecutor = backgroundExecutor;
        mActivityStarter = activityStarter;
@@ -149,8 +152,8 @@ public class MediaControlPanel {
        mMediaOutputDialogFactory = mediaOutputDialogFactory;
        mMediaCarouselController = mediaCarouselController;
        mFalsingManager = falsingManager;
        mMediaFlags = mediaFlags;
        mSystemClock = systemClock;

        loadDimens();

        mSeekBarViewModel.setLogSmartspaceClick(() -> {
@@ -426,14 +429,34 @@ public class MediaControlPanel {
        deviceName.setText(deviceString);
        seamlessView.setContentDescription(deviceString);

        // Media action buttons
        List<MediaAction> actionIcons = data.getActions();
        List<Integer> actionsWhenCollapsed = data.getActionsToShowInCompact();
        // Media controls

        if (mMediaFlags.areMediaSessionActionsEnabled() && data.getSemanticActions() != null) {
            // Use PlaybackState actions instead
            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;
        List<MediaAction> actionIcons = data.getActions();
        for (; i < actionIcons.size() && i < ACTION_IDS.length; i++) {
            int actionId = ACTION_IDS[i];
            boolean visibleInCompat = actionsWhenCollapsed.contains(i);
            final ImageButton button = mPlayerViewHolder.getAction(actionId);
            MediaAction mediaAction = actionIcons.get(i);
            if (mediaAction != null) {
                button.setImageIcon(mediaAction.getIcon());
                button.setContentDescription(mediaAction.getContentDescription());
                Runnable action = mediaAction.getAction();
@@ -450,9 +473,17 @@ public class MediaControlPanel {
                        }
                    });
                }
            boolean visibleInCompat = actionsWhenCollapsed.contains(i);
                setVisibleAndAlpha(collapsedSet, actionId, visibleInCompat);
                setVisibleAndAlpha(expandedSet, actionId, true /*visible */);
            } else {
                button.setImageIcon(null);
                button.setContentDescription(null);
                button.setEnabled(false);
                setVisibleAndAlpha(collapsedSet, actionId, visibleInCompat);
                // for expanded layout, set as INVISIBLE so that we still reserve space in the UI
                expandedSet.setVisibility(actionId, ConstraintSet.INVISIBLE);
                expandedSet.setAlpha(actionId, 0.0f);
            }
        }

        // Hide any unused buttons
+32 −1
Original line number Diff line number Diff line
@@ -47,13 +47,18 @@ data class MediaData(
     */
    val artwork: Icon?,
    /**
     * List of actions that can be performed on the player: prev, next, play, pause, etc.
     * List of generic action buttons for the media player, based on notification actions
     */
    val actions: List<MediaAction>,
    /**
     * Same as above, but shown on smaller versions of the player, like in QQS or keyguard.
     */
    val actionsToShowInCompact: List<Int>,
    /**
     * Semantic actions buttons, based on the PlaybackState of the media session.
     * If present, these actions will be preferred in the UI over [actions]
     */
    val semanticActions: MediaButton? = null,
    /**
     * Package name of the app that's posting the media.
     */
@@ -125,6 +130,32 @@ data class MediaData(
    }
}

/**
 * Contains [MediaAction] objects which represent specific buttons in the UI
 */
data class MediaButton(
    /**
     * Play/pause button
     */
    var playOrPause: MediaAction? = null,
    /**
     * Next button, or custom action
     */
    var nextOrCustom: MediaAction? = null,
    /**
     * Previous button, or custom action
     */
    var prevOrCustom: MediaAction? = null,
    /**
     * First custom action space
     */
    var startCustom: MediaAction? = null,
    /**
     * Last custom action space
     */
    var endCustom: MediaAction? = null
)

/** State of a media action. */
data class MediaAction(
    val icon: Icon?,
Loading