public final class

CommandButton

extends java.lang.Object

 java.lang.Object

↳androidx.media3.session.CommandButton

Gradle dependencies

compile group: 'androidx.media3', name: 'media3-session', version: '1.5.0-alpha01'

  • groupId: androidx.media3
  • artifactId: media3-session
  • version: 1.5.0-alpha01

Artifact androidx.media3:media3-session:1.5.0-alpha01 it located at Google repository (https://maven.google.com/)

Overview

A button for a SessionCommand or that can be displayed by controllers.

Summary

Fields
public final java.lang.CharSequencedisplayName

The display name of the button.

public final Bundleextras

The extra of the button.

public final inticon

The CommandButton.Icon of the button.

public static final intICON_ALBUM

An icon showing an album symbol (a stylized LP record).

public static final intICON_ARTIST

An icon showing an artist symbol (a stylized person with a musical note).

public static final intICON_BLOCK

An icon showing a block symbol (a circle with a diagonal line).

public static final intICON_BOOKMARK_FILLED

An icon showing a filled bookmark symbol.

public static final intICON_BOOKMARK_UNFILLED

An icon showing an unfilled bookmark symbol.

public static final intICON_CHECK_CIRCLE_FILLED

An icon showing a filled circle with a check mark.

public static final intICON_CHECK_CIRCLE_UNFILLED

An icon showing a unfilled circle with a check mark.

public static final intICON_CLOSED_CAPTIONS

An icon showing a closed caption symbol (a rectangle with the letters CC).

public static final intICON_CLOSED_CAPTIONS_OFF

An icon showing a closed caption off symbol (a rectangle with the letters CC, with a large diagonal line across).

public static final intICON_FAST_FORWARD

An icon showing a fast forward symbol (two right facing triangles).

public static final intICON_FEED

An icon showing an feed symbol (a dot in the bottom-left with multiple concentric quarter circles).

public static final intICON_FLAG_FILLED

An icon showing a filled flag symbol.

public static final intICON_FLAG_UNFILLED

An icon showing an unfilled flag symbol.

public static final intICON_HEART_FILLED

An icon showing a filled heart symbol.

public static final intICON_HEART_UNFILLED

An icon showing an unfilled heart symbol.

public static final intICON_MINUS

An icon showing a minus symbol.

public static final intICON_MINUS_CIRCLE_FILLED

An icon showing a filled circle with a minus.

public static final intICON_MINUS_CIRCLE_UNFILLED

An icon showing an unfilled circle with a minus.

public static final intICON_NEXT

An icon showing a next symbol (a right facing triangle with a vertical bar).

public static final intICON_PAUSE

An icon showing a pause symbol (two vertical bars).

public static final intICON_PLAY

An icon showing a play symbol (a right facing triangle).

public static final intICON_PLAYBACK_SPEED

An icon showing a playback speed symbol (a right facing triangle in a circle with half-dashed, half-solid contour).

public static final intICON_PLAYBACK_SPEED_0_5

An icon showing a 0.5x speed symbol.

public static final intICON_PLAYBACK_SPEED_0_8

An icon showing a 0.8x speed symbol.

public static final intICON_PLAYBACK_SPEED_1_0

An icon showing a 1.0x speed symbol.

public static final intICON_PLAYBACK_SPEED_1_2

An icon showing a 1.2x speed symbol.

public static final intICON_PLAYBACK_SPEED_1_5

An icon showing a 1.5x speed symbol.

public static final intICON_PLAYBACK_SPEED_1_8

An icon showing a 1.8x speed symbol.

public static final intICON_PLAYBACK_SPEED_2_0

An icon showing a 2.0x speed symbol.

public static final intICON_PLAYLIST_ADD

An icon showing an add to playlist symbol (multiple horizontal bars with a small plus).

public static final intICON_PLAYLIST_REMOVE

An icon showing an remove from playlist symbol (multiple horizontal bars with a small minus).

public static final intICON_PLUS

An icon showing a plus symbol.

public static final intICON_PLUS_CIRCLE_FILLED

An icon showing a filled circle with a plus.

public static final intICON_PLUS_CIRCLE_UNFILLED

An icon showing an unfilled circle with a plus.

public static final intICON_PREVIOUS

An icon showing a previous symbol (a left facing triangle with a vertical bar).

public static final intICON_QUALITY

An icon showing a quality selection symbol (multiple horizontal bars with sliders).

public static final intICON_QUEUE_ADD

An icon showing an add to queue symbol (a stylized TV with a plus).

public static final intICON_QUEUE_NEXT

An icon showing a play next queue item symbol (a stylized TV with a plus and a right-facing arrow).

public static final intICON_QUEUE_REMOVE

An icon showing a remove from queue symbol (a stylized TV with a minus).

public static final intICON_RADIO

An icon showing a radio symbol (left and right facing sound waves).

public static final intICON_REPEAT_ALL

An icon showing a repeat all symbol (two open clockwise arrows).

public static final intICON_REPEAT_OFF

An icon showing a disabled repeat symbol (two open clockwise arrows, in a color representing a disabled state).

public static final intICON_REPEAT_ONE

An icon showing a repeat one symbol (two open clockwise arrows with an overlaid number 1).

public static final intICON_REWIND

An icon showing a rewind symbol (two left facing triangles).

public static final intICON_SETTINGS

An icon showing a settings symbol (a stylized cog).

public static final intICON_SHARE

An icon showing a share symbol (three dots connected by two diagonal lines, open on the right).

public static final intICON_SHUFFLE_OFF

An icon showing a disabled shuffle symbol (two diagonal upward and downward facing arrows, in a color representing a disabled state).

public static final intICON_SHUFFLE_ON

An icon showing a shuffle symbol (two diagonal upward and downward facing arrows).

public static final intICON_SHUFFLE_STAR

An icon showing a shuffle symbol with a start (two diagonal upward and downward facing arrows with an overlaid star).

public static final intICON_SIGNAL

An icon showing an signal symbol (a vertical mast with circular sounds waves).

public static final intICON_SKIP_BACK

An icon showing a skip back symbol (an open anti-clockwise arrow).

public static final intICON_SKIP_BACK_10

An icon showing a skip back 10 seconds symbol (an open anti-clockwise arrow with the number 10).

public static final intICON_SKIP_BACK_15

An icon showing a skip back 15 seconds symbol (an open anti-clockwise arrow with the number 15).

public static final intICON_SKIP_BACK_30

An icon showing a skip back 30 seconds symbol (an open anti-clockwise arrow with the number 30).

public static final intICON_SKIP_BACK_5

An icon showing a skip back 5 seconds symbol (an open anti-clockwise arrow with the number 5).

public static final intICON_SKIP_FORWARD

An icon showing a skip forward symbol (an open clock-wise arrow).

public static final intICON_SKIP_FORWARD_10

An icon showing a skip forward 10 seconds symbol (an open clockwise arrow with the number 10).

public static final intICON_SKIP_FORWARD_15

An icon showing a skip forward 15 seconds symbol (an open clockwise arrow with the number 15).

public static final intICON_SKIP_FORWARD_30

An icon showing a skip forward 30 seconds symbol (an open clockwise arrow with the number 30).

public static final intICON_SKIP_FORWARD_5

An icon showing a skip forward 5 seconds symbol (an open clockwise arrow with the number 5).

public static final intICON_STAR_FILLED

An icon showing a filled star symbol.

public static final intICON_STAR_UNFILLED

An icon showing an unfilled star symbol.

public static final intICON_STOP

An icon showing a stop symbol (a square).

public static final intICON_SUBTITLES

An icon showing a subtitles symbol (a rectangle filled with dots and horizontal lines).

public static final intICON_SUBTITLES_OFF

An icon showing a subtitles off symbol (a rectangle filled with dots and horizontal lines, with a large diagonal line across).

public static final intICON_SYNC

An icon showing a sync symbol (two open anti-clockwise arrows).

public static final intICON_THUMB_DOWN_FILLED

An icon showing a filled thumb-down symbol.

public static final intICON_THUMB_DOWN_UNFILLED

An icon showing an unfilled thumb-down symbol.

public static final intICON_THUMB_UP_FILLED

An icon showing a filled thumb-up symbol.

public static final intICON_THUMB_UP_UNFILLED

An icon showing an unfilled thumb-up symbol.

public static final intICON_UNDEFINED

An icon constant representing an undefined icon, for example a custom icon not covered by the existing constants.

public static final intICON_VOLUME_DOWN

An icon showing a volume down symbol (a stylized speaker with a single small sound wave).

public static final intICON_VOLUME_OFF

An icon showing a volume off symbol (a stylized speaker with multiple sound waves, with a large diagonal line across).

public static final intICON_VOLUME_UP

An icon showing a volume up symbol (a stylized speaker with multiple sound waves).

public final inticonResId

The icon resource id of the button that is used when the predefined CommandButton.icon is not available or set to CommandButton.ICON_UNDEFINED.

public final UriiconUri

The for the icon of the button that is used when the predefined CommandButton.icon is not available or set to CommandButton.ICON_UNDEFINED.

public final booleanisEnabled

Whether the button is enabled.

public final intplayerCommand

The command of the button.

public final SessionCommandsessionCommand

The session command of the button.

Methods
public booleanequals(java.lang.Object obj)

Checks the given command button for equality while ignoring CommandButton.extras.

public static CommandButtonfromBundle(Bundle bundle)

public static CommandButtonfromBundle(Bundle bundle, int sessionInterfaceVersion)

Restores a CommandButton from a .

public static intgetIconResIdForIconConstant(int icon)

Returns a drawable resource id for the given CommandButton.Icon constant.

public inthashCode()

public BundletoBundle()

from java.lang.Objectclone, finalize, getClass, notify, notifyAll, toString, wait, wait, wait

Fields

public static final int ICON_UNDEFINED

An icon constant representing an undefined icon, for example a custom icon not covered by the existing constants.

public static final int ICON_PLAY

An icon showing a play symbol (a right facing triangle).

public static final int ICON_PAUSE

An icon showing a pause symbol (two vertical bars).

public static final int ICON_STOP

An icon showing a stop symbol (a square).

public static final int ICON_NEXT

An icon showing a next symbol (a right facing triangle with a vertical bar).

public static final int ICON_PREVIOUS

An icon showing a previous symbol (a left facing triangle with a vertical bar).

public static final int ICON_SKIP_FORWARD

An icon showing a skip forward symbol (an open clock-wise arrow).

public static final int ICON_SKIP_FORWARD_5

An icon showing a skip forward 5 seconds symbol (an open clockwise arrow with the number 5).

public static final int ICON_SKIP_FORWARD_10

An icon showing a skip forward 10 seconds symbol (an open clockwise arrow with the number 10).

public static final int ICON_SKIP_FORWARD_15

An icon showing a skip forward 15 seconds symbol (an open clockwise arrow with the number 15).

public static final int ICON_SKIP_FORWARD_30

An icon showing a skip forward 30 seconds symbol (an open clockwise arrow with the number 30).

public static final int ICON_SKIP_BACK

An icon showing a skip back symbol (an open anti-clockwise arrow).

public static final int ICON_SKIP_BACK_5

An icon showing a skip back 5 seconds symbol (an open anti-clockwise arrow with the number 5).

public static final int ICON_SKIP_BACK_10

An icon showing a skip back 10 seconds symbol (an open anti-clockwise arrow with the number 10).

public static final int ICON_SKIP_BACK_15

An icon showing a skip back 15 seconds symbol (an open anti-clockwise arrow with the number 15).

public static final int ICON_SKIP_BACK_30

An icon showing a skip back 30 seconds symbol (an open anti-clockwise arrow with the number 30).

public static final int ICON_FAST_FORWARD

An icon showing a fast forward symbol (two right facing triangles).

public static final int ICON_REWIND

An icon showing a rewind symbol (two left facing triangles).

public static final int ICON_REPEAT_ALL

An icon showing a repeat all symbol (two open clockwise arrows).

public static final int ICON_REPEAT_ONE

An icon showing a repeat one symbol (two open clockwise arrows with an overlaid number 1).

public static final int ICON_REPEAT_OFF

An icon showing a disabled repeat symbol (two open clockwise arrows, in a color representing a disabled state).

public static final int ICON_SHUFFLE_ON

An icon showing a shuffle symbol (two diagonal upward and downward facing arrows).

public static final int ICON_SHUFFLE_OFF

An icon showing a disabled shuffle symbol (two diagonal upward and downward facing arrows, in a color representing a disabled state).

public static final int ICON_SHUFFLE_STAR

An icon showing a shuffle symbol with a start (two diagonal upward and downward facing arrows with an overlaid star).

public static final int ICON_HEART_FILLED

An icon showing a filled heart symbol.

public static final int ICON_HEART_UNFILLED

An icon showing an unfilled heart symbol.

public static final int ICON_STAR_FILLED

An icon showing a filled star symbol.

public static final int ICON_STAR_UNFILLED

An icon showing an unfilled star symbol.

public static final int ICON_BOOKMARK_FILLED

An icon showing a filled bookmark symbol.

public static final int ICON_BOOKMARK_UNFILLED

An icon showing an unfilled bookmark symbol.

public static final int ICON_THUMB_UP_FILLED

An icon showing a filled thumb-up symbol.

public static final int ICON_THUMB_UP_UNFILLED

An icon showing an unfilled thumb-up symbol.

public static final int ICON_THUMB_DOWN_FILLED

An icon showing a filled thumb-down symbol.

public static final int ICON_THUMB_DOWN_UNFILLED

An icon showing an unfilled thumb-down symbol.

public static final int ICON_FLAG_FILLED

An icon showing a filled flag symbol.

public static final int ICON_FLAG_UNFILLED

An icon showing an unfilled flag symbol.

public static final int ICON_PLUS

An icon showing a plus symbol.

public static final int ICON_MINUS

An icon showing a minus symbol.

public static final int ICON_PLAYLIST_ADD

An icon showing an add to playlist symbol (multiple horizontal bars with a small plus).

public static final int ICON_PLAYLIST_REMOVE

An icon showing an remove from playlist symbol (multiple horizontal bars with a small minus).

public static final int ICON_QUEUE_ADD

An icon showing an add to queue symbol (a stylized TV with a plus).

public static final int ICON_QUEUE_NEXT

An icon showing a play next queue item symbol (a stylized TV with a plus and a right-facing arrow).

public static final int ICON_QUEUE_REMOVE

An icon showing a remove from queue symbol (a stylized TV with a minus).

public static final int ICON_BLOCK

An icon showing a block symbol (a circle with a diagonal line).

public static final int ICON_PLUS_CIRCLE_FILLED

An icon showing a filled circle with a plus.

public static final int ICON_PLUS_CIRCLE_UNFILLED

An icon showing an unfilled circle with a plus.

public static final int ICON_MINUS_CIRCLE_FILLED

An icon showing a filled circle with a minus.

public static final int ICON_MINUS_CIRCLE_UNFILLED

An icon showing an unfilled circle with a minus.

public static final int ICON_CHECK_CIRCLE_FILLED

An icon showing a filled circle with a check mark.

public static final int ICON_CHECK_CIRCLE_UNFILLED

An icon showing a unfilled circle with a check mark.

public static final int ICON_PLAYBACK_SPEED

An icon showing a playback speed symbol (a right facing triangle in a circle with half-dashed, half-solid contour).

public static final int ICON_PLAYBACK_SPEED_0_5

An icon showing a 0.5x speed symbol.

public static final int ICON_PLAYBACK_SPEED_0_8

An icon showing a 0.8x speed symbol.

public static final int ICON_PLAYBACK_SPEED_1_0

An icon showing a 1.0x speed symbol.

public static final int ICON_PLAYBACK_SPEED_1_2

An icon showing a 1.2x speed symbol.

public static final int ICON_PLAYBACK_SPEED_1_5

An icon showing a 1.5x speed symbol.

public static final int ICON_PLAYBACK_SPEED_1_8

An icon showing a 1.8x speed symbol.

public static final int ICON_PLAYBACK_SPEED_2_0

An icon showing a 2.0x speed symbol.

public static final int ICON_SETTINGS

An icon showing a settings symbol (a stylized cog).

public static final int ICON_QUALITY

An icon showing a quality selection symbol (multiple horizontal bars with sliders).

public static final int ICON_SUBTITLES

An icon showing a subtitles symbol (a rectangle filled with dots and horizontal lines).

public static final int ICON_SUBTITLES_OFF

An icon showing a subtitles off symbol (a rectangle filled with dots and horizontal lines, with a large diagonal line across).

public static final int ICON_CLOSED_CAPTIONS

An icon showing a closed caption symbol (a rectangle with the letters CC).

public static final int ICON_CLOSED_CAPTIONS_OFF

An icon showing a closed caption off symbol (a rectangle with the letters CC, with a large diagonal line across).

public static final int ICON_SYNC

An icon showing a sync symbol (two open anti-clockwise arrows).

public static final int ICON_SHARE

An icon showing a share symbol (three dots connected by two diagonal lines, open on the right).

public static final int ICON_VOLUME_UP

An icon showing a volume up symbol (a stylized speaker with multiple sound waves).

public static final int ICON_VOLUME_DOWN

An icon showing a volume down symbol (a stylized speaker with a single small sound wave).

public static final int ICON_VOLUME_OFF

An icon showing a volume off symbol (a stylized speaker with multiple sound waves, with a large diagonal line across).

public static final int ICON_ARTIST

An icon showing an artist symbol (a stylized person with a musical note).

public static final int ICON_ALBUM

An icon showing an album symbol (a stylized LP record).

public static final int ICON_RADIO

An icon showing a radio symbol (left and right facing sound waves).

public static final int ICON_SIGNAL

An icon showing an signal symbol (a vertical mast with circular sounds waves).

public static final int ICON_FEED

An icon showing an feed symbol (a dot in the bottom-left with multiple concentric quarter circles).

public final SessionCommand sessionCommand

The session command of the button. Will be null if CommandButton.playerCommand is set.

public final int playerCommand

The command of the button. Will be Player.COMMAND_INVALID if CommandButton.sessionCommand is set.

public final int icon

The CommandButton.Icon of the button.

public final int iconResId

The icon resource id of the button that is used when the predefined CommandButton.icon is not available or set to CommandButton.ICON_UNDEFINED. Can be 0 if not needed.

public final Uri iconUri

The for the icon of the button that is used when the predefined CommandButton.icon is not available or set to CommandButton.ICON_UNDEFINED. Can be null.

Note that this value can be used in addition or instead of CommandButton.iconResId for consumers that are capable of loading the .

public final java.lang.CharSequence displayName

The display name of the button. Can be empty if the command is predefined and a custom name isn't needed.

public final Bundle extras

The extra of the button. It's private information between session and controller.

public final boolean isEnabled

Whether the button is enabled.

Note that this value will be set to false for MediaController instances if the corresponding command is not available to this controller (see CommandButton.playerCommand and CommandButton.sessionCommand).

Methods

public boolean equals(java.lang.Object obj)

Checks the given command button for equality while ignoring CommandButton.extras.

public int hashCode()

public Bundle toBundle()

public static CommandButton fromBundle(Bundle bundle)

Deprecated: Use CommandButton.fromBundle(Bundle, int) instead.

public static CommandButton fromBundle(Bundle bundle, int sessionInterfaceVersion)

Restores a CommandButton from a .

public static int getIconResIdForIconConstant(int icon)

Returns a drawable resource id for the given CommandButton.Icon constant.

Parameters:

icon: The CommandButton.Icon.

Returns:

The drawable resource if for the icon, or 0 if not found.

Source

/*
 * Copyright 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package androidx.media3.session;

import static androidx.media3.common.util.Assertions.checkArgument;
import static androidx.media3.common.util.Assertions.checkNotNull;
import static androidx.media3.common.util.Assertions.checkState;
import static java.lang.annotation.ElementType.TYPE_USE;

import android.net.Uri;
import android.os.Bundle;
import android.text.TextUtils;
import androidx.annotation.DrawableRes;
import androidx.annotation.IntDef;
import androidx.annotation.Nullable;
import androidx.media3.common.Player;
import androidx.media3.common.util.UnstableApi;
import androidx.media3.common.util.Util;
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableList;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import com.google.errorprone.annotations.CheckReturnValue;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.List;

/**
 * A button for a {@link SessionCommand} or {@link Player.Command} that can be displayed by
 * controllers.
 *
 * @see MediaSession#setCustomLayout(MediaSession.ControllerInfo, List)
 * @see MediaController.Listener#onCustomLayoutChanged(MediaController, List)
 */
public final class CommandButton {

  // TODO: b/328238954 - Stabilize these constants and the corresponding methods, and deprecate the
  //  methods that do not use these constants.
  /** An icon constant for a button. Must be one of the {@code CommandButton.ICON_} constants. */
  @UnstableApi
  @Documented
  @Retention(RetentionPolicy.SOURCE)
  @Target(TYPE_USE)
  @IntDef({
    ICON_UNDEFINED,
    ICON_PLAY,
    ICON_PAUSE,
    ICON_STOP,
    ICON_NEXT,
    ICON_PREVIOUS,
    ICON_SKIP_FORWARD,
    ICON_SKIP_FORWARD_5,
    ICON_SKIP_FORWARD_10,
    ICON_SKIP_FORWARD_15,
    ICON_SKIP_FORWARD_30,
    ICON_SKIP_BACK,
    ICON_SKIP_BACK_5,
    ICON_SKIP_BACK_10,
    ICON_SKIP_BACK_15,
    ICON_SKIP_BACK_30,
    ICON_FAST_FORWARD,
    ICON_REWIND,
    ICON_REPEAT_ALL,
    ICON_REPEAT_ONE,
    ICON_REPEAT_OFF,
    ICON_SHUFFLE_ON,
    ICON_SHUFFLE_OFF,
    ICON_SHUFFLE_STAR,
    ICON_HEART_FILLED,
    ICON_HEART_UNFILLED,
    ICON_STAR_FILLED,
    ICON_STAR_UNFILLED,
    ICON_BOOKMARK_FILLED,
    ICON_BOOKMARK_UNFILLED,
    ICON_THUMB_UP_FILLED,
    ICON_THUMB_UP_UNFILLED,
    ICON_THUMB_DOWN_FILLED,
    ICON_THUMB_DOWN_UNFILLED,
    ICON_FLAG_FILLED,
    ICON_FLAG_UNFILLED,
    ICON_PLUS,
    ICON_MINUS,
    ICON_PLAYLIST_ADD,
    ICON_PLAYLIST_REMOVE,
    ICON_QUEUE_ADD,
    ICON_QUEUE_NEXT,
    ICON_QUEUE_REMOVE,
    ICON_BLOCK,
    ICON_PLUS_CIRCLE_FILLED,
    ICON_PLUS_CIRCLE_UNFILLED,
    ICON_MINUS_CIRCLE_FILLED,
    ICON_MINUS_CIRCLE_UNFILLED,
    ICON_CHECK_CIRCLE_FILLED,
    ICON_CHECK_CIRCLE_UNFILLED,
    ICON_PLAYBACK_SPEED,
    ICON_PLAYBACK_SPEED_0_5,
    ICON_PLAYBACK_SPEED_0_8,
    ICON_PLAYBACK_SPEED_1_0,
    ICON_PLAYBACK_SPEED_1_2,
    ICON_PLAYBACK_SPEED_1_5,
    ICON_PLAYBACK_SPEED_1_8,
    ICON_PLAYBACK_SPEED_2_0,
    ICON_SETTINGS,
    ICON_QUALITY,
    ICON_SUBTITLES,
    ICON_SUBTITLES_OFF,
    ICON_CLOSED_CAPTIONS,
    ICON_CLOSED_CAPTIONS_OFF,
    ICON_SYNC,
    ICON_SHARE,
    ICON_VOLUME_UP,
    ICON_VOLUME_DOWN,
    ICON_VOLUME_OFF,
    ICON_ARTIST,
    ICON_ALBUM,
    ICON_RADIO,
    ICON_SIGNAL,
    ICON_FEED
  })
  public @interface Icon {}

  // Note: The constant values of these icons matches the Material Design code points.

  /**
   * An icon constant representing an undefined icon, for example a custom icon not covered by the
   * existing constants.
   */
  @UnstableApi public static final int ICON_UNDEFINED = 0;

  /** An icon showing a play symbol (a right facing triangle). */
  @UnstableApi public static final int ICON_PLAY = 0xe037;

  /** An icon showing a pause symbol (two vertical bars). */
  @UnstableApi public static final int ICON_PAUSE = 0xe034;

  /** An icon showing a stop symbol (a square). */
  @UnstableApi public static final int ICON_STOP = 0xe047;

  /** An icon showing a next symbol (a right facing triangle with a vertical bar). */
  @UnstableApi public static final int ICON_NEXT = 0xe044;

  /** An icon showing a previous symbol (a left facing triangle with a vertical bar). */
  @UnstableApi public static final int ICON_PREVIOUS = 0xe045;

  /** An icon showing a skip forward symbol (an open clock-wise arrow). */
  @UnstableApi public static final int ICON_SKIP_FORWARD = 0xf6f4;

  /**
   * An icon showing a skip forward 5 seconds symbol (an open clockwise arrow with the number 5).
   */
  @UnstableApi public static final int ICON_SKIP_FORWARD_5 = 0xe058;

  /**
   * An icon showing a skip forward 10 seconds symbol (an open clockwise arrow with the number 10).
   */
  @UnstableApi public static final int ICON_SKIP_FORWARD_10 = 0xe056;

  /**
   * An icon showing a skip forward 15 seconds symbol (an open clockwise arrow with the number 15).
   */
  @UnstableApi public static final int ICON_SKIP_FORWARD_15 = 0xfe056;

  /**
   * An icon showing a skip forward 30 seconds symbol (an open clockwise arrow with the number 30).
   */
  @UnstableApi public static final int ICON_SKIP_FORWARD_30 = 0xe057;

  /** An icon showing a skip back symbol (an open anti-clockwise arrow). */
  @UnstableApi public static final int ICON_SKIP_BACK = 0xe042;

  /**
   * An icon showing a skip back 5 seconds symbol (an open anti-clockwise arrow with the number 5).
   */
  @UnstableApi public static final int ICON_SKIP_BACK_5 = 0xe05b;

  /**
   * An icon showing a skip back 10 seconds symbol (an open anti-clockwise arrow with the number
   * 10).
   */
  @UnstableApi public static final int ICON_SKIP_BACK_10 = 0xe059;

  /**
   * An icon showing a skip back 15 seconds symbol (an open anti-clockwise arrow with the number
   * 15).
   */
  @UnstableApi public static final int ICON_SKIP_BACK_15 = 0xfe059;

  /**
   * An icon showing a skip back 30 seconds symbol (an open anti-clockwise arrow with the number
   * 30).
   */
  @UnstableApi public static final int ICON_SKIP_BACK_30 = 0xe05a;

  /** An icon showing a fast forward symbol (two right facing triangles). */
  @UnstableApi public static final int ICON_FAST_FORWARD = 0xe01f;

  /** An icon showing a rewind symbol (two left facing triangles). */
  @UnstableApi public static final int ICON_REWIND = 0xe020;

  /** An icon showing a repeat all symbol (two open clockwise arrows). */
  @UnstableApi public static final int ICON_REPEAT_ALL = 0xe040;

  /** An icon showing a repeat one symbol (two open clockwise arrows with an overlaid number 1). */
  @UnstableApi public static final int ICON_REPEAT_ONE = 0xe041;

  /**
   * An icon showing a disabled repeat symbol (two open clockwise arrows, in a color representing a
   * disabled state).
   */
  @UnstableApi public static final int ICON_REPEAT_OFF = 0xfe040;

  /** An icon showing a shuffle symbol (two diagonal upward and downward facing arrows). */
  @UnstableApi public static final int ICON_SHUFFLE_ON = 0xe043;

  /**
   * An icon showing a disabled shuffle symbol (two diagonal upward and downward facing arrows, in a
   * color representing a disabled state).
   */
  @UnstableApi public static final int ICON_SHUFFLE_OFF = 0xfe044;

  /**
   * An icon showing a shuffle symbol with a start (two diagonal upward and downward facing arrows
   * with an overlaid star).
   */
  @UnstableApi public static final int ICON_SHUFFLE_STAR = 0xfe043;

  /** An icon showing a filled heart symbol. */
  @UnstableApi public static final int ICON_HEART_FILLED = 0xfe87d;

  /** An icon showing an unfilled heart symbol. */
  @UnstableApi public static final int ICON_HEART_UNFILLED = 0xe87d;

  /** An icon showing a filled star symbol. */
  @UnstableApi public static final int ICON_STAR_FILLED = 0xfe838;

  /** An icon showing an unfilled star symbol. */
  @UnstableApi public static final int ICON_STAR_UNFILLED = 0xe838;

  /** An icon showing a filled bookmark symbol. */
  @UnstableApi public static final int ICON_BOOKMARK_FILLED = 0xfe866;

  /** An icon showing an unfilled bookmark symbol. */
  @UnstableApi public static final int ICON_BOOKMARK_UNFILLED = 0xe866;

  /** An icon showing a filled thumb-up symbol. */
  @UnstableApi public static final int ICON_THUMB_UP_FILLED = 0xfe8dc;

  /** An icon showing an unfilled thumb-up symbol. */
  @UnstableApi public static final int ICON_THUMB_UP_UNFILLED = 0xe8dc;

  /** An icon showing a filled thumb-down symbol. */
  @UnstableApi public static final int ICON_THUMB_DOWN_FILLED = 0xfe8db;

  /** An icon showing an unfilled thumb-down symbol. */
  @UnstableApi public static final int ICON_THUMB_DOWN_UNFILLED = 0xe8db;

  /** An icon showing a filled flag symbol. */
  @UnstableApi public static final int ICON_FLAG_FILLED = 0xfe153;

  /** An icon showing an unfilled flag symbol. */
  @UnstableApi public static final int ICON_FLAG_UNFILLED = 0xe153;

  /** An icon showing a plus symbol. */
  @UnstableApi public static final int ICON_PLUS = 0xe145;

  /** An icon showing a minus symbol. */
  @UnstableApi public static final int ICON_MINUS = 0xe15b;

  /** An icon showing an add to playlist symbol (multiple horizontal bars with a small plus). */
  @UnstableApi public static final int ICON_PLAYLIST_ADD = 0xe03b;

  /**
   * An icon showing an remove from playlist symbol (multiple horizontal bars with a small minus).
   */
  @UnstableApi public static final int ICON_PLAYLIST_REMOVE = 0xeb80;

  /** An icon showing an add to queue symbol (a stylized TV with a plus). */
  @UnstableApi public static final int ICON_QUEUE_ADD = 0xe05c;

  /**
   * An icon showing a play next queue item symbol (a stylized TV with a plus and a right-facing
   * arrow).
   */
  @UnstableApi public static final int ICON_QUEUE_NEXT = 0xe066;

  /** An icon showing a remove from queue symbol (a stylized TV with a minus). */
  @UnstableApi public static final int ICON_QUEUE_REMOVE = 0xe067;

  /** An icon showing a block symbol (a circle with a diagonal line). */
  @UnstableApi public static final int ICON_BLOCK = 0xe14b;

  /** An icon showing a filled circle with a plus. */
  @UnstableApi public static final int ICON_PLUS_CIRCLE_FILLED = 0xfe147;

  /** An icon showing an unfilled circle with a plus. */
  @UnstableApi public static final int ICON_PLUS_CIRCLE_UNFILLED = 0xe147;

  /** An icon showing a filled circle with a minus. */
  @UnstableApi public static final int ICON_MINUS_CIRCLE_FILLED = 0xfe148;

  /** An icon showing an unfilled circle with a minus. */
  @UnstableApi public static final int ICON_MINUS_CIRCLE_UNFILLED = 0xfe149;

  /** An icon showing a filled circle with a check mark. */
  @UnstableApi public static final int ICON_CHECK_CIRCLE_FILLED = 0xfe86c;

  /** An icon showing a unfilled circle with a check mark. */
  @UnstableApi public static final int ICON_CHECK_CIRCLE_UNFILLED = 0xe86c;

  /**
   * An icon showing a playback speed symbol (a right facing triangle in a circle with half-dashed,
   * half-solid contour).
   */
  @UnstableApi public static final int ICON_PLAYBACK_SPEED = 0xe068;

  /** An icon showing a 0.5x speed symbol. */
  @UnstableApi public static final int ICON_PLAYBACK_SPEED_0_5 = 0xf4e2;

  /** An icon showing a 0.8x speed symbol. */
  @UnstableApi public static final int ICON_PLAYBACK_SPEED_0_8 = 0xff4e2;

  /** An icon showing a 1.0x speed symbol. */
  @UnstableApi public static final int ICON_PLAYBACK_SPEED_1_0 = 0xefcd;

  /** An icon showing a 1.2x speed symbol. */
  @UnstableApi public static final int ICON_PLAYBACK_SPEED_1_2 = 0xf4e1;

  /** An icon showing a 1.5x speed symbol. */
  @UnstableApi public static final int ICON_PLAYBACK_SPEED_1_5 = 0xf4e0;

  /** An icon showing a 1.8x speed symbol. */
  @UnstableApi public static final int ICON_PLAYBACK_SPEED_1_8 = 0xff4e0;

  /** An icon showing a 2.0x speed symbol. */
  @UnstableApi public static final int ICON_PLAYBACK_SPEED_2_0 = 0xf4eb;

  /** An icon showing a settings symbol (a stylized cog). */
  @UnstableApi public static final int ICON_SETTINGS = 0xe8b8;

  /** An icon showing a quality selection symbol (multiple horizontal bars with sliders). */
  @UnstableApi public static final int ICON_QUALITY = 0xe429;

  /** An icon showing a subtitles symbol (a rectangle filled with dots and horizontal lines). */
  @UnstableApi public static final int ICON_SUBTITLES = 0xe048;

  /**
   * An icon showing a subtitles off symbol (a rectangle filled with dots and horizontal lines, with
   * a large diagonal line across).
   */
  @UnstableApi public static final int ICON_SUBTITLES_OFF = 0xef72;

  /** An icon showing a closed caption symbol (a rectangle with the letters CC). */
  @UnstableApi public static final int ICON_CLOSED_CAPTIONS = 0xe01c;

  /**
   * An icon showing a closed caption off symbol (a rectangle with the letters CC, with a large
   * diagonal line across).
   */
  @UnstableApi public static final int ICON_CLOSED_CAPTIONS_OFF = 0xf1dc;

  /** An icon showing a sync symbol (two open anti-clockwise arrows). */
  @UnstableApi public static final int ICON_SYNC = 0xe627;

  /**
   * An icon showing a share symbol (three dots connected by two diagonal lines, open on the right).
   */
  @UnstableApi public static final int ICON_SHARE = 0xe80d;

  /** An icon showing a volume up symbol (a stylized speaker with multiple sound waves). */
  @UnstableApi public static final int ICON_VOLUME_UP = 0xe050;

  /** An icon showing a volume down symbol (a stylized speaker with a single small sound wave). */
  @UnstableApi public static final int ICON_VOLUME_DOWN = 0xe04d;

  /**
   * An icon showing a volume off symbol (a stylized speaker with multiple sound waves, with a large
   * diagonal line across).
   */
  @UnstableApi public static final int ICON_VOLUME_OFF = 0xe04f;

  /** An icon showing an artist symbol (a stylized person with a musical note). */
  @UnstableApi public static final int ICON_ARTIST = 0xe01a;

  /** An icon showing an album symbol (a stylized LP record). */
  @UnstableApi public static final int ICON_ALBUM = 0xe019;

  /** An icon showing a radio symbol (left and right facing sound waves). */
  @UnstableApi public static final int ICON_RADIO = 0xe51e;

  /** An icon showing an signal symbol (a vertical mast with circular sounds waves). */
  @UnstableApi public static final int ICON_SIGNAL = 0xf048;

  /**
   * An icon showing an feed symbol (a dot in the bottom-left with multiple concentric quarter
   * circles).
   */
  @UnstableApi public static final int ICON_FEED = 0xe0e5;

  /** A builder for {@link CommandButton}. */
  public static final class Builder {

    @Nullable private SessionCommand sessionCommand;
    private @Player.Command int playerCommand;
    private @Icon int icon;
    @DrawableRes private int iconResId;
    @Nullable private Uri iconUri;
    private CharSequence displayName;
    private Bundle extras;
    private boolean enabled;

    /**
     * [will be deprecated] Use {@link #Builder(int)} instead to define the {@link Icon} for this
     * button. A separate resource id via {@link #setIconResId(int)} or {@link #setIconUri} is no
     * longer required unless for {@link #ICON_UNDEFINED}.
     */
    public Builder() {
      this(ICON_UNDEFINED);
    }

    /**
     * Creates a builder.
     *
     * @param icon The {@link Icon} that should be shown for this button.
     */
    @UnstableApi
    public Builder(@Icon int icon) {
      this(icon, getIconResIdForIconConstant(icon));
    }

    // Internal version of constructor that assigns an additionally known icon resource id
    // immediately. This is needed for R8 resource shrinking efficiency to know that the icon
    // doesn't need to be resolved to any of the bundled icon drawables.
    /* package */ Builder(@Icon int icon, @DrawableRes int iconResId) {
      this.icon = icon;
      this.iconResId = iconResId;
      displayName = "";
      extras = Bundle.EMPTY;
      playerCommand = Player.COMMAND_INVALID;
      icon = ICON_UNDEFINED;
      enabled = true;
    }

    /**
     * Sets the {@link SessionCommand} that is required to be {@linkplain
     * MediaController#isSessionCommandAvailable available} when the button is clicked.
     *
     * <p>Cannot set this if a player command is already set via {@link #setPlayerCommand(int)}.
     *
     * @param sessionCommand The {@link SessionCommand}.
     * @return This builder for chaining.
     */
    @CanIgnoreReturnValue
    public Builder setSessionCommand(SessionCommand sessionCommand) {
      checkNotNull(sessionCommand, "sessionCommand should not be null.");
      checkArgument(
          playerCommand == Player.COMMAND_INVALID,
          "playerCommands is already set. Only one of sessionCommand and playerCommand should be"
              + " set.");
      this.sessionCommand = sessionCommand;
      return this;
    }

    /**
     * Sets the {@link Player.Command} that is required to be {@linkplain
     * MediaController#isCommandAvailable available} when the button is clicked.
     *
     * <p>Cannot set this if a session command is already set via {@link
     * #setSessionCommand(SessionCommand)}.
     *
     * @param playerCommand The {@link Player.Command}.
     * @return This builder for chaining.
     */
    @CanIgnoreReturnValue
    public Builder setPlayerCommand(@Player.Command int playerCommand) {
      checkArgument(
          sessionCommand == null,
          "sessionCommand is already set. Only one of sessionCommand and playerCommand should be"
              + " set.");
      this.playerCommand = playerCommand;
      return this;
    }

    /**
     * [will be deprecated] The icon should be defined with the constructor {@link Icon} parameter
     * in {@link #Builder(int)} instead. Only in case the existing list of icons is not sufficient,
     * use {@link #ICON_UNDEFINED} and set a separate resource id with {@link #setCustomIconResId}.
     */
    @CanIgnoreReturnValue
    public Builder setIconResId(@DrawableRes int resId) {
      return setCustomIconResId(resId);
    }

    /**
     * Sets the resource id of an icon that is used when the predefined {@link Icon} is not
     * available or set to {@link #ICON_UNDEFINED}.
     *
     * @param resId The resource id of a custom icon.
     * @return This builder for chaining.
     */
    @UnstableApi
    @CanIgnoreReturnValue
    public Builder setCustomIconResId(@DrawableRes int resId) {
      iconResId = resId;
      return this;
    }

    /**
     * Sets a {@link Uri} for the icon of this button.
     *
     * <p>Note that this {@link Uri} may be used when the predefined {@link Icon} is not available
     * or set to {@link #ICON_UNDEFINED}. It can be used in addition or instead of {@link
     * #setCustomIconResId} for consumers that are capable of loading the {@link Uri}.
     *
     * @param uri The uri to an icon.
     * @return This builder for chaining.
     */
    @UnstableApi
    @CanIgnoreReturnValue
    public Builder setIconUri(Uri uri) {
      this.iconUri = uri;
      return this;
    }

    /**
     * Sets a display name of this button.
     *
     * @param displayName The display name.
     * @return This builder for chaining.
     */
    @CanIgnoreReturnValue
    public Builder setDisplayName(CharSequence displayName) {
      this.displayName = displayName;
      return this;
    }

    /**
     * Sets whether the button is enabled.
     *
     * <p>Note that this value will be set to {@code false} for {@link MediaController} instances if
     * the corresponding command is not available to this controller (see {@link #setPlayerCommand}
     * and {@link #setSessionCommand}).
     *
     * <p>The default value is {@code true}.
     *
     * @param enabled Whether the button is enabled.
     * @return This builder for chaining.
     */
    @CanIgnoreReturnValue
    public Builder setEnabled(boolean enabled) {
      this.enabled = enabled;
      return this;
    }

    /**
     * Sets an extra {@link Bundle} of this button.
     *
     * @param extras The extra {@link Bundle}.
     * @return This builder for chaining.
     */
    @CanIgnoreReturnValue
    public Builder setExtras(Bundle extras) {
      this.extras = new Bundle(extras);
      return this;
    }

    /** Builds a {@link CommandButton}. */
    public CommandButton build() {
      checkState(
          (sessionCommand == null) != (playerCommand == Player.COMMAND_INVALID),
          "Exactly one of sessionCommand and playerCommand should be set");
      return new CommandButton(
          sessionCommand, playerCommand, icon, iconResId, iconUri, displayName, extras, enabled);
    }
  }

  /** The session command of the button. Will be {@code null} if {@link #playerCommand} is set. */
  @Nullable public final SessionCommand sessionCommand;

  /**
   * The {@link Player.Command} command of the button. Will be {@link Player#COMMAND_INVALID} if
   * {@link #sessionCommand} is set.
   */
  public final @Player.Command int playerCommand;

  /** The {@link Icon} of the button. */
  @UnstableApi public final @Icon int icon;

  /**
   * The icon resource id of the button that is used when the predefined {@link #icon} is not
   * available or set to {@link #ICON_UNDEFINED}. Can be {@code 0} if not needed.
   */
  @DrawableRes public final int iconResId;

  /**
   * The {@link Uri} for the icon of the button that is used when the predefined {@link #icon} is
   * not available or set to {@link #ICON_UNDEFINED}. Can be {@code null}.
   *
   * <p>Note that this value can be used in addition or instead of {@link #iconResId} for consumers
   * that are capable of loading the {@link Uri}.
   */
  @UnstableApi @Nullable public final Uri iconUri;

  /**
   * The display name of the button. Can be empty if the command is predefined and a custom name
   * isn't needed.
   */
  public final CharSequence displayName;

  /**
   * The extra {@link Bundle} of the button. It's private information between session and
   * controller.
   */
  @UnstableApi public final Bundle extras;

  /**
   * Whether the button is enabled.
   *
   * <p>Note that this value will be set to {@code false} for {@link MediaController} instances if
   * the corresponding command is not available to this controller (see {@link #playerCommand} and
   * {@link #sessionCommand}).
   */
  public final boolean isEnabled;

  private CommandButton(
      @Nullable SessionCommand sessionCommand,
      @Player.Command int playerCommand,
      @Icon int icon,
      @DrawableRes int iconResId,
      @Nullable Uri iconUri,
      CharSequence displayName,
      Bundle extras,
      boolean enabled) {
    this.sessionCommand = sessionCommand;
    this.playerCommand = playerCommand;
    this.icon = icon;
    this.iconResId = iconResId;
    this.iconUri = iconUri;
    this.displayName = displayName;
    this.extras = new Bundle(extras);
    this.isEnabled = enabled;
  }

  /** Returns a copy with the new {@link #isEnabled} flag. */
  @CheckReturnValue
  /* package */ CommandButton copyWithIsEnabled(boolean isEnabled) {
    // Because this method is supposed to be used by the library only, this method has been chosen
    // over the conventional `buildUpon` approach. This aims for keeping this separate from the
    // public Builder-API used by apps.
    if (this.isEnabled == isEnabled) {
      return this;
    }
    return new CommandButton(
        sessionCommand,
        playerCommand,
        icon,
        iconResId,
        iconUri,
        displayName,
        new Bundle(extras),
        isEnabled);
  }

  /** Checks the given command button for equality while ignoring {@link #extras}. */
  @Override
  public boolean equals(@Nullable Object obj) {
    if (this == obj) {
      return true;
    }
    if (!(obj instanceof CommandButton)) {
      return false;
    }
    CommandButton button = (CommandButton) obj;
    return Objects.equal(sessionCommand, button.sessionCommand)
        && playerCommand == button.playerCommand
        && icon == button.icon
        && iconResId == button.iconResId
        && Objects.equal(iconUri, button.iconUri)
        && TextUtils.equals(displayName, button.displayName)
        && isEnabled == button.isEnabled;
  }

  @Override
  public int hashCode() {
    return Objects.hashCode(
        sessionCommand, playerCommand, icon, iconResId, displayName, isEnabled, iconUri);
  }

  /**
   * Returns a list of command buttons with the {@link CommandButton#isEnabled} flag set to false if
   * the corresponding command is not available.
   */
  /* package */ static ImmutableList<CommandButton> copyWithUnavailableButtonsDisabled(
      List<CommandButton> commandButtons,
      SessionCommands sessionCommands,
      Player.Commands playerCommands) {
    ImmutableList.Builder<CommandButton> updatedButtons = new ImmutableList.Builder<>();
    for (int i = 0; i < commandButtons.size(); i++) {
      CommandButton button = commandButtons.get(i);
      if (isButtonCommandAvailable(button, sessionCommands, playerCommands)) {
        updatedButtons.add(button);
      } else {
        updatedButtons.add(button.copyWithIsEnabled(false));
      }
    }
    return updatedButtons.build();
  }

  /**
   * Returns whether the required command ({@link #playerCommand} or {@link #sessionCommand}) for
   * the button is available.
   *
   * @param button The command button.
   * @param sessionCommands The available session commands.
   * @param playerCommands The available player commands.
   * @return Whether the command required for this button is available.
   */
  /* package */ static boolean isButtonCommandAvailable(
      CommandButton button, SessionCommands sessionCommands, Player.Commands playerCommands) {
    return (button.sessionCommand != null && sessionCommands.contains(button.sessionCommand))
        || (button.playerCommand != Player.COMMAND_INVALID
            && playerCommands.contains(button.playerCommand));
  }

  private static final String FIELD_SESSION_COMMAND = Util.intToStringMaxRadix(0);
  private static final String FIELD_PLAYER_COMMAND = Util.intToStringMaxRadix(1);
  private static final String FIELD_ICON_RES_ID = Util.intToStringMaxRadix(2);
  private static final String FIELD_DISPLAY_NAME = Util.intToStringMaxRadix(3);
  private static final String FIELD_EXTRAS = Util.intToStringMaxRadix(4);
  private static final String FIELD_ENABLED = Util.intToStringMaxRadix(5);
  private static final String FIELD_ICON_URI = Util.intToStringMaxRadix(6);
  private static final String FIELD_ICON = Util.intToStringMaxRadix(7);

  @UnstableApi
  public Bundle toBundle() {
    Bundle bundle = new Bundle();
    if (sessionCommand != null) {
      bundle.putBundle(FIELD_SESSION_COMMAND, sessionCommand.toBundle());
    }
    if (playerCommand != Player.COMMAND_INVALID) {
      bundle.putInt(FIELD_PLAYER_COMMAND, playerCommand);
    }
    if (icon != ICON_UNDEFINED) {
      bundle.putInt(FIELD_ICON, icon);
    }
    if (iconResId != 0) {
      bundle.putInt(FIELD_ICON_RES_ID, iconResId);
    }
    if (displayName != "") {
      bundle.putCharSequence(FIELD_DISPLAY_NAME, displayName);
    }
    if (!extras.isEmpty()) {
      bundle.putBundle(FIELD_EXTRAS, extras);
    }
    if (iconUri != null) {
      bundle.putParcelable(FIELD_ICON_URI, iconUri);
    }
    if (!isEnabled) {
      bundle.putBoolean(FIELD_ENABLED, isEnabled);
    }
    return bundle;
  }

  /**
   * @deprecated Use {@link #fromBundle(Bundle, int)} instead.
   */
  @Deprecated
  @UnstableApi
  public static CommandButton fromBundle(Bundle bundle) {
    return fromBundle(bundle, MediaSessionStub.VERSION_INT);
  }

  /** Restores a {@code CommandButton} from a {@link Bundle}. */
  @UnstableApi
  public static CommandButton fromBundle(Bundle bundle, int sessionInterfaceVersion) {
    @Nullable Bundle sessionCommandBundle = bundle.getBundle(FIELD_SESSION_COMMAND);
    @Nullable
    SessionCommand sessionCommand =
        sessionCommandBundle == null ? null : SessionCommand.fromBundle(sessionCommandBundle);
    @Player.Command
    int playerCommand =
        bundle.getInt(FIELD_PLAYER_COMMAND, /* defaultValue= */ Player.COMMAND_INVALID);
    int iconResId = bundle.getInt(FIELD_ICON_RES_ID, /* defaultValue= */ 0);
    CharSequence displayName = bundle.getCharSequence(FIELD_DISPLAY_NAME, /* defaultValue= */ "");
    @Nullable Bundle extras = bundle.getBundle(FIELD_EXTRAS);
    // Before sessionInterfaceVersion == 3, the session expected this value to be meaningless and we
    // can only assume it was meant to be true.
    boolean enabled =
        sessionInterfaceVersion < 3 || bundle.getBoolean(FIELD_ENABLED, /* defaultValue= */ true);
    @Nullable Uri iconUri = bundle.getParcelable(FIELD_ICON_URI);
    @Icon int icon = bundle.getInt(FIELD_ICON, /* defaultValue= */ ICON_UNDEFINED);
    Builder builder = new Builder(icon, iconResId);
    if (sessionCommand != null) {
      builder.setSessionCommand(sessionCommand);
    }
    if (playerCommand != Player.COMMAND_INVALID) {
      builder.setPlayerCommand(playerCommand);
    }
    if (iconUri != null) {
      builder.setIconUri(iconUri);
    }
    return builder
        .setDisplayName(displayName)
        .setExtras(extras == null ? Bundle.EMPTY : extras)
        .setEnabled(enabled)
        .build();
  }

  /**
   * Returns a drawable resource id for the given {@link Icon} constant.
   *
   * @param icon The {@link Icon}.
   * @return The drawable resource if for the {@code icon}, or 0 if not found.
   */
  @UnstableApi
  @DrawableRes
  public static int getIconResIdForIconConstant(@Icon int icon) {
    switch (icon) {
      case ICON_PLAY:
        return R.drawable.media3_icon_play;
      case ICON_PAUSE:
        return R.drawable.media3_icon_pause;
      case ICON_STOP:
        return R.drawable.media3_icon_stop;
      case ICON_NEXT:
        return R.drawable.media3_icon_next;
      case ICON_PREVIOUS:
        return R.drawable.media3_icon_previous;
      case ICON_SKIP_FORWARD:
        return R.drawable.media3_icon_skip_forward;
      case ICON_SKIP_FORWARD_5:
        return R.drawable.media3_icon_skip_forward_5;
      case ICON_SKIP_FORWARD_10:
        return R.drawable.media3_icon_skip_forward_10;
      case ICON_SKIP_FORWARD_15:
        return R.drawable.media3_icon_skip_forward_15;
      case ICON_SKIP_FORWARD_30:
        return R.drawable.media3_icon_skip_forward_30;
      case ICON_SKIP_BACK:
        return R.drawable.media3_icon_skip_back;
      case ICON_SKIP_BACK_5:
        return R.drawable.media3_icon_skip_back_5;
      case ICON_SKIP_BACK_10:
        return R.drawable.media3_icon_skip_back_10;
      case ICON_SKIP_BACK_15:
        return R.drawable.media3_icon_skip_back_15;
      case ICON_SKIP_BACK_30:
        return R.drawable.media3_icon_skip_back_30;
      case ICON_FAST_FORWARD:
        return R.drawable.media3_icon_fast_forward;
      case ICON_REWIND:
        return R.drawable.media3_icon_rewind;
      case ICON_REPEAT_ALL:
        return R.drawable.media3_icon_repeat_all;
      case ICON_REPEAT_ONE:
        return R.drawable.media3_icon_repeat_one;
      case ICON_REPEAT_OFF:
        return R.drawable.media3_icon_repeat_off;
      case ICON_SHUFFLE_ON:
        return R.drawable.media3_icon_shuffle_on;
      case ICON_SHUFFLE_OFF:
        return R.drawable.media3_icon_shuffle_off;
      case ICON_SHUFFLE_STAR:
        return R.drawable.media3_icon_shuffle_star;
      case ICON_HEART_FILLED:
        return R.drawable.media3_icon_heart_filled;
      case ICON_HEART_UNFILLED:
        return R.drawable.media3_icon_heart_unfilled;
      case ICON_STAR_FILLED:
        return R.drawable.media3_icon_star_filled;
      case ICON_STAR_UNFILLED:
        return R.drawable.media3_icon_star_unfilled;
      case ICON_BOOKMARK_FILLED:
        return R.drawable.media3_icon_bookmark_filled;
      case ICON_BOOKMARK_UNFILLED:
        return R.drawable.media3_icon_bookmark_unfilled;
      case ICON_THUMB_UP_FILLED:
        return R.drawable.media3_icon_thumb_up_filled;
      case ICON_THUMB_UP_UNFILLED:
        return R.drawable.media3_icon_thumb_up_unfilled;
      case ICON_THUMB_DOWN_FILLED:
        return R.drawable.media3_icon_thumb_down_filled;
      case ICON_THUMB_DOWN_UNFILLED:
        return R.drawable.media3_icon_thumb_down_unfilled;
      case ICON_FLAG_FILLED:
        return R.drawable.media3_icon_flag_filled;
      case ICON_FLAG_UNFILLED:
        return R.drawable.media3_icon_flag_unfilled;
      case ICON_PLUS:
        return R.drawable.media3_icon_plus;
      case ICON_MINUS:
        return R.drawable.media3_icon_minus;
      case ICON_PLAYLIST_ADD:
        return R.drawable.media3_icon_playlist_add;
      case ICON_PLAYLIST_REMOVE:
        return R.drawable.media3_icon_playlist_remove;
      case ICON_QUEUE_ADD:
        return R.drawable.media3_icon_queue_add;
      case ICON_QUEUE_NEXT:
        return R.drawable.media3_icon_queue_next;
      case ICON_QUEUE_REMOVE:
        return R.drawable.media3_icon_queue_remove;
      case ICON_BLOCK:
        return R.drawable.media3_icon_block;
      case ICON_PLUS_CIRCLE_FILLED:
        return R.drawable.media3_icon_plus_circle_filled;
      case ICON_PLUS_CIRCLE_UNFILLED:
        return R.drawable.media3_icon_plus_circle_unfilled;
      case ICON_MINUS_CIRCLE_FILLED:
        return R.drawable.media3_icon_minus_circle_filled;
      case ICON_MINUS_CIRCLE_UNFILLED:
        return R.drawable.media3_icon_minus_circle_unfilled;
      case ICON_CHECK_CIRCLE_FILLED:
        return R.drawable.media3_icon_check_circle_filled;
      case ICON_CHECK_CIRCLE_UNFILLED:
        return R.drawable.media3_icon_check_circle_unfilled;
      case ICON_PLAYBACK_SPEED:
        return R.drawable.media3_icon_playback_speed;
      case ICON_PLAYBACK_SPEED_0_5:
        return R.drawable.media3_icon_playback_speed_0_5;
      case ICON_PLAYBACK_SPEED_0_8:
        return R.drawable.media3_icon_playback_speed_0_8;
      case ICON_PLAYBACK_SPEED_1_0:
        return R.drawable.media3_icon_playback_speed_1_0;
      case ICON_PLAYBACK_SPEED_1_2:
        return R.drawable.media3_icon_playback_speed_1_2;
      case ICON_PLAYBACK_SPEED_1_5:
        return R.drawable.media3_icon_playback_speed_1_5;
      case ICON_PLAYBACK_SPEED_1_8:
        return R.drawable.media3_icon_playback_speed_1_8;
      case ICON_PLAYBACK_SPEED_2_0:
        return R.drawable.media3_icon_playback_speed_2_0;
      case ICON_SETTINGS:
        return R.drawable.media3_icon_settings;
      case ICON_QUALITY:
        return R.drawable.media3_icon_quality;
      case ICON_SUBTITLES:
        return R.drawable.media3_icon_subtitles;
      case ICON_SUBTITLES_OFF:
        return R.drawable.media3_icon_subtitles_off;
      case ICON_CLOSED_CAPTIONS:
        return R.drawable.media3_icon_closed_captions;
      case ICON_CLOSED_CAPTIONS_OFF:
        return R.drawable.media3_icon_closed_captions_off;
      case ICON_SYNC:
        return R.drawable.media3_icon_sync;
      case ICON_SHARE:
        return R.drawable.media3_icon_share;
      case ICON_VOLUME_UP:
        return R.drawable.media3_icon_volume_up;
      case ICON_VOLUME_DOWN:
        return R.drawable.media3_icon_volume_down;
      case ICON_VOLUME_OFF:
        return R.drawable.media3_icon_volume_off;
      case ICON_ARTIST:
        return R.drawable.media3_icon_artist;
      case ICON_ALBUM:
        return R.drawable.media3_icon_album;
      case ICON_RADIO:
        return R.drawable.media3_icon_radio;
      case ICON_SIGNAL:
        return R.drawable.media3_icon_signal;
      case ICON_FEED:
        return R.drawable.media3_icon_feed;
      default:
        return 0;
    }
  }
}