Files
Android-pyApi/android_pyapi/android/media_session.py
T
shuiyu1123 506f9ac725 feat: 新增 42 个 Android API 模块
新增模块覆盖:
系统层 (14): system, security, print, opengl, renderscript, transition,
test, service_notification, service_controls, service_quicksettings,
service_wallpaper, service_autofill, service_dreams, service_vr

应用层 (13): app_admin, app_backup, app_job, app_usage, app_role,
app_people, appwidget, companion, credentials, mtp, sip, telecom, speech

硬件媒体层 (15): hardware_display, hardware_fingerprint, hardware_usb,
hardware_input, media_audiofx, media_browse, media_session, media_tv,
media_midi, media_projection, uwb, se, view_autofill, view_textclassifier,
view_translation

总计 94 个模块,75,342 行代码
2026-06-24 12:00:28 +00:00

854 lines
29 KiB
Python

"""
Android media.session 组件 — MediaSession, MediaController, PlaybackState, MediaMetadata 等
方法签名完全对齐 Android SDK
"""
import time
from typing import Any, Callable, Dict, List, Optional, Set, Union
from .._core import Stub, AndroidOnlyError
# ═══════════════════════════════════════════════════════════════
# MediaSession
# ═══════════════════════════════════════════════════════════════
class MediaSession(Stub):
"""MediaSession — 媒体会话"""
FLAG_HANDLES_MEDIA_BUTTONS = 1
FLAG_HANDLES_TRANSPORT_CONTROLS = 2
FLAG_EXCLUSIVE_GLOBAL_PRIORITY = 4
# ═══════════════════════════════════════════════════════════
# Callback
# ═══════════════════════════════════════════════════════════
class Callback(Stub):
"""MediaSession.Callback — 会话回调"""
def onPlay(self):
pass
def onPause(self):
pass
def onSkipToNext(self):
pass
def onSkipToPrevious(self):
pass
def onFastForward(self):
pass
def onRewind(self):
pass
def onStop(self):
pass
def onSeekTo(self, pos: int):
pass
def onSetRating(self, rating: "Rating"):
pass
def onSetRepeatMode(self, repeatMode: int):
pass
def onSetShuffleMode(self, shuffleMode: int):
pass
def onCommand(self, command: str, extras: Any, cb: Any):
pass
def onCustomAction(self, action: str, extras: Any):
pass
def onMediaButtonEvent(self, mediaButtonIntent: Any) -> bool:
return False
def onPlayFromMediaId(self, mediaId: str, extras: Any):
pass
def onPlayFromSearch(self, query: str, extras: Any):
pass
def onPlayFromUri(self, uri: str, extras: Any):
pass
def onPrepare(self):
pass
def onPrepareFromMediaId(self, mediaId: str, extras: Any):
pass
def onPrepareFromSearch(self, query: str, extras: Any):
pass
def onPrepareFromUri(self, uri: str, extras: Any):
pass
def __init__(self, context: Any = None, tag: str = "",
token: "SessionToken" = None):
super().__init__()
self._tag = tag
self._token = token or SessionToken()
self._active = False
self._flags = 0
self._session_activity: Any = None
self._callback: Optional[MediaSession.Callback] = None
self._metadata: Optional["MediaMetadata"] = None
self._playback_state: Optional["PlaybackState"] = None
self._queue: List["QueueItem"] = []
self._queue_title: Optional[str] = None
self._extras: Any = None
self._rating_type = Rating.RATING_NONE
self._repeat_mode = PlaybackState.REPEAT_MODE_NONE
self._shuffle_mode = PlaybackState.SHUFFLE_MODE_NONE
self._captioning_enabled = False
self._controllers: List[MediaController] = []
def setSessionActivity(self, sessionActivity: Any):
self._session_activity = sessionActivity
def sendSessionEvent(self, event: str, extras: Any):
for ctrl in self._controllers:
ctrl._callback.onSessionEvent(event, extras)
def release(self):
self._active = False
self._controllers.clear()
def getSessionToken(self) -> "SessionToken":
return self._token
def setFlags(self, flags: int):
self._flags = flags
def setPlaybackToLocal(self, volumeProvider: Any = None):
pass
def setPlaybackToRemote(self, volumeProvider: Any):
pass
def setActive(self, active: bool):
self._active = active
def isActive(self) -> bool:
return self._active
def setMediaMetadata(self, metadata: "MediaMetadata"):
self._metadata = metadata
for ctrl in self._controllers:
ctrl._callback.onMetadataChanged(metadata)
def setPlaybackState(self, state: "PlaybackState"):
self._playback_state = state
for ctrl in self._controllers:
ctrl._callback.onPlaybackStateChanged(state)
def setQueue(self, queue: List["QueueItem"]):
self._queue = queue
for ctrl in self._controllers:
ctrl._callback.onQueueChanged(queue)
def setQueueTitle(self, title: str):
self._queue_title = title
for ctrl in self._controllers:
ctrl._callback.onQueueTitleChanged(title)
def setExtras(self, extras: Any):
self._extras = extras
for ctrl in self._controllers:
ctrl._callback.onExtrasChanged(extras)
def setMetadata(self, metadata: "MediaMetadata"):
self.setMediaMetadata(metadata)
def setRatingType(self, ratingType: int):
self._rating_type = ratingType
def setRepeatMode(self, repeatMode: int):
self._repeat_mode = repeatMode
for ctrl in self._controllers:
ctrl._callback.onRepeatModeChanged(repeatMode)
def setShuffleMode(self, shuffleMode: int):
self._shuffle_mode = shuffleMode
for ctrl in self._controllers:
ctrl._callback.onShuffleModeChanged(shuffleMode)
def setCaptioningEnabled(self, enabled: bool):
self._captioning_enabled = enabled
for ctrl in self._controllers:
ctrl._callback.onCaptioningEnabledChanged(enabled)
def getController(self) -> "MediaController":
ctrl = MediaController(self)
self._controllers.append(ctrl)
return ctrl
def getCallerPackageName(self) -> str:
return "com.android.systemui"
def setCallback(self, callback: Callback, handler: Any = None):
self._callback = callback
# ═══════════════════════════════════════════════════════════════
# MediaController
# ═══════════════════════════════════════════════════════════════
class MediaController(Stub):
"""MediaController — 媒体控制器"""
# ═══════════════════════════════════════════════════════════
# Callback
# ═══════════════════════════════════════════════════════════
class Callback(Stub):
"""MediaController.Callback — 控制器回调"""
def onSessionReady(self):
pass
def onSessionDestroyed(self):
pass
def onSessionEvent(self, event: str, extras: Any):
pass
def onPlaybackStateChanged(self, state: "PlaybackState"):
pass
def onMetadataChanged(self, metadata: "MediaMetadata"):
pass
def onQueueChanged(self, queue: List["QueueItem"]):
pass
def onQueueTitleChanged(self, title: str):
pass
def onExtrasChanged(self, extras: Any):
pass
def onAudioInfoChanged(self, info: Any):
pass
def onCaptioningEnabledChanged(self, enabled: bool):
pass
def onRepeatModeChanged(self, repeatMode: int):
pass
def onShuffleModeChanged(self, shuffleMode: int):
pass
# ═══════════════════════════════════════════════════════════
# TransportControls
# ═══════════════════════════════════════════════════════════
class TransportControls(Stub):
"""MediaController.TransportControls — 传输控制"""
def __init__(self, session: "MediaSession"):
super().__init__()
self._session = session
def play(self):
if self._session._callback:
self._session._callback.onPlay()
def pause(self):
if self._session._callback:
self._session._callback.onPause()
def stop(self):
if self._session._callback:
self._session._callback.onStop()
def fastForward(self):
if self._session._callback:
self._session._callback.onFastForward()
def rewind(self):
if self._session._callback:
self._session._callback.onRewind()
def skipToNext(self):
if self._session._callback:
self._session._callback.onSkipToNext()
def skipToPrevious(self):
if self._session._callback:
self._session._callback.onSkipToPrevious()
def seekTo(self, pos: int):
if self._session._callback:
self._session._callback.onSeekTo(pos)
def setRating(self, rating: "Rating"):
if self._session._callback:
self._session._callback.onSetRating(rating)
def setRepeatMode(self, repeatMode: int):
if self._session._callback:
self._session._callback.onSetRepeatMode(repeatMode)
def setShuffleMode(self, shuffleMode: int):
if self._session._callback:
self._session._callback.onSetShuffleMode(shuffleMode)
def sendCustomAction(self, action: str, extras: Any):
if self._session._callback:
self._session._callback.onCustomAction(action, extras)
def playFromMediaId(self, mediaId: str, extras: Any):
if self._session._callback:
self._session._callback.onPlayFromMediaId(mediaId, extras)
def playFromSearch(self, query: str, extras: Any):
if self._session._callback:
self._session._callback.onPlayFromSearch(query, extras)
def playFromUri(self, uri: str, extras: Any):
if self._session._callback:
self._session._callback.onPlayFromUri(uri, extras)
def prepare(self):
if self._session._callback:
self._session._callback.onPrepare()
def prepareFromMediaId(self, mediaId: str, extras: Any):
if self._session._callback:
self._session._callback.onPrepareFromMediaId(mediaId, extras)
def prepareFromSearch(self, query: str, extras: Any):
if self._session._callback:
self._session._callback.onPrepareFromSearch(query, extras)
def prepareFromUri(self, uri: str, extras: Any):
if self._session._callback:
self._session._callback.onPrepareFromUri(uri, extras)
def __init__(self, session: "MediaSession" = None):
super().__init__()
self._session = session
self._callback = MediaController.Callback()
self._transport_controls = MediaController.TransportControls(session)
def getSessionToken(self) -> "SessionToken":
return self._session.getSessionToken() if self._session else SessionToken()
def getTransportControls(self) -> TransportControls:
return self._transport_controls
def getPlaybackState(self) -> Optional["PlaybackState"]:
return self._session._playback_state if self._session else None
def getMetadata(self) -> Optional["MediaMetadata"]:
return self._session._metadata if self._session else None
def getQueueTitle(self) -> Optional[str]:
return self._session._queue_title if self._session else None
def getQueue(self) -> List["QueueItem"]:
return self._session._queue if self._session else []
def getRepeatMode(self) -> int:
return self._session._repeat_mode if self._session else PlaybackState.REPEAT_MODE_NONE
def getShuffleMode(self) -> int:
return self._session._shuffle_mode if self._session else PlaybackState.SHUFFLE_MODE_NONE
def getRatingType(self) -> int:
return self._session._rating_type if self._session else Rating.RATING_NONE
def getExtras(self) -> Any:
return self._session._extras if self._session else None
def getFlags(self) -> int:
return self._session._flags if self._session else 0
def getPackageName(self) -> str:
return self._session.getCallerPackageName() if self._session else ""
def getSessionActivity(self) -> Any:
return self._session._session_activity if self._session else None
def registerCallback(self, callback: Callback, handler: Any = None):
self._callback = callback
def unregisterCallback(self, callback: Callback):
self._callback = MediaController.Callback()
def sendCommand(self, command: str, extras: Any, cb: Any):
if self._session and self._session._callback:
self._session._callback.onCommand(command, extras, cb)
def adjustVolume(self, direction: int, flags: int):
pass
def setVolumeTo(self, value: int, flags: int):
pass
def isSessionReady(self) -> bool:
return True
# ═══════════════════════════════════════════════════════════════
# PlaybackState
# ═══════════════════════════════════════════════════════════════
class PlaybackState(Stub):
"""PlaybackState — 播放状态"""
STATE_NONE = 0
STATE_STOPPED = 1
STATE_PAUSED = 2
STATE_PLAYING = 3
STATE_FAST_FORWARDING = 4
STATE_REWINDING = 5
STATE_BUFFERING = 6
STATE_ERROR = 7
STATE_CONNECTING = 8
STATE_SKIPPING_TO_PREVIOUS = 9
STATE_SKIPPING_TO_NEXT = 10
STATE_SKIPPING_TO_QUEUE_ITEM = 11
ACTION_PLAY = 1 << 0
ACTION_PAUSE = 1 << 1
ACTION_PLAY_PAUSE = 1 << 2
ACTION_STOP = 1 << 3
ACTION_SEEK_TO = 1 << 4
ACTION_FAST_FORWARD = 1 << 5
ACTION_REWIND = 1 << 6
ACTION_SKIP_TO_NEXT = 1 << 7
ACTION_SKIP_TO_PREVIOUS = 1 << 8
ACTION_SET_RATING = 1 << 9
ACTION_SET_REPEAT_MODE = 1 << 10
ACTION_SET_SHUFFLE_MODE = 1 << 11
ACTION_SET_CAPTIONING_ENABLED = 1 << 12
ACTION_SKIP_TO_QUEUE_ITEM = 1 << 13
ACTION_PLAY_FROM_MEDIA_ID = 1 << 14
ACTION_PLAY_FROM_SEARCH = 1 << 15
ACTION_PREPARE = 1 << 16
ACTION_PREPARE_FROM_MEDIA_ID = 1 << 17
ACTION_PREPARE_FROM_SEARCH = 1 << 18
ACTION_PREPARE_FROM_URI = 1 << 19
ACTION_PLAY_FROM_URI = 1 << 20
REPEAT_MODE_NONE = 0
REPEAT_MODE_ONE = 1
REPEAT_MODE_ALL = 2
REPEAT_MODE_GROUP = 3
SHUFFLE_MODE_NONE = 0
SHUFFLE_MODE_ALL = 1
SHUFFLE_MODE_GROUP = 2
class Builder(Stub):
"""PlaybackState.Builder — 播放状态构建器"""
def __init__(self):
super().__init__()
self._state = PlaybackState.STATE_NONE
self._position = 0
self._speed = 1.0
self._actions = 0
self._custom_actions: List[Any] = []
self._active_queue_item_id = -1
self._error_message: Optional[str] = None
self._extras: Any = None
self._buffered_position = 0
def setState(self, state: int, position: int, speed: float) -> "PlaybackState.Builder":
self._state = state
self._position = position
self._speed = speed
return self
def setActions(self, actions: int) -> "PlaybackState.Builder":
self._actions = actions
return self
def setCustomAction(self, action: str, name: str, icon: Any = None) -> "PlaybackState.Builder":
self._custom_actions.append((action, name, icon))
return self
def setActiveQueueItemId(self, id: int) -> "PlaybackState.Builder":
self._active_queue_item_id = id
return self
def setErrorMessage(self, error: str) -> "PlaybackState.Builder":
self._error_message = error
return self
def setExtras(self, extras: Any) -> "PlaybackState.Builder":
self._extras = extras
return self
def setBufferedPosition(self, bufferedPosition: int) -> "PlaybackState.Builder":
self._buffered_position = bufferedPosition
return self
def setPosition(self, position: int) -> "PlaybackState.Builder":
self._position = position
return self
def setSpeed(self, speed: float) -> "PlaybackState.Builder":
self._speed = speed
return self
def addCustomAction(self, action: "PlaybackState.CustomAction") -> "PlaybackState.Builder":
self._custom_actions.append(action)
return self
def build(self) -> "PlaybackState":
ps = PlaybackState()
ps._state = self._state
ps._position = self._position
ps._speed = self._speed
ps._actions = self._actions
ps._custom_actions = self._custom_actions
ps._active_queue_item_id = self._active_queue_item_id
ps._error_message = self._error_message
ps._extras = self._extras
ps._buffered_position = self._buffered_position
return ps
class CustomAction(Stub):
"""PlaybackState.CustomAction — 自定义操作"""
def __init__(self, action: str, name: str, icon: Any = None):
super().__init__()
self._action = action
self._name = name
self._icon = icon
def getAction(self) -> str:
return self._action
def getName(self) -> str:
return self._name
def getIcon(self) -> Any:
return self._icon
def __init__(self):
super().__init__()
self._state = PlaybackState.STATE_NONE
self._position = 0
self._speed = 1.0
self._actions = 0
self._custom_actions: List[Any] = []
self._active_queue_item_id = -1
self._error_message: Optional[str] = None
self._extras: Any = None
self._buffered_position = 0
self._last_position_update_time = int(time.time() * 1000)
def getState(self) -> int:
return self._state
def getPosition(self) -> int:
return self._position
def getPlaybackSpeed(self) -> float:
return self._speed
def getActions(self) -> int:
return self._actions
def getCustomActions(self) -> List[Any]:
return self._custom_actions
def getActiveQueueItemId(self) -> int:
return self._active_queue_item_id
def getErrorMessage(self) -> Optional[str]:
return self._error_message
def getExtras(self) -> Any:
return self._extras
def getBufferedPosition(self) -> int:
return self._buffered_position
def getLastPositionUpdateTime(self) -> int:
return self._last_position_update_time
def toString(self) -> str:
state_names = {
PlaybackState.STATE_NONE: "NONE",
PlaybackState.STATE_STOPPED: "STOPPED",
PlaybackState.STATE_PAUSED: "PAUSED",
PlaybackState.STATE_PLAYING: "PLAYING",
}
return f"PlaybackState(state={state_names.get(self._state, str(self._state))}," \
f" pos={self._position})"
# ═══════════════════════════════════════════════════════════════
# MediaMetadata
# ═══════════════════════════════════════════════════════════════
class MediaMetadata(Stub):
"""MediaMetadata — 媒体元数据"""
METADATA_KEY_ALBUM = "android.media.metadata.ALBUM"
METADATA_KEY_ALBUM_ART = "android.media.metadata.ALBUM_ART"
METADATA_KEY_ALBUM_ARTIST = "android.media.metadata.ALBUM_ARTIST"
METADATA_KEY_ALBUM_ART_URI = "android.media.metadata.ALBUM_ART_URI"
METADATA_KEY_ART = "android.media.metadata.ART"
METADATA_KEY_ARTIST = "android.media.metadata.ARTIST"
METADATA_KEY_ART_URI = "android.media.metadata.ART_URI"
METADATA_KEY_AUTHOR = "android.media.metadata.AUTHOR"
METADATA_KEY_COMPILATION = "android.media.metadata.COMPILATION"
METADATA_KEY_COMPOSER = "android.media.metadata.COMPOSER"
METADATA_KEY_DATE = "android.media.metadata.DATE"
METADATA_KEY_DISC_NUMBER = "android.media.metadata.DISC_NUMBER"
METADATA_KEY_DISPLAY_DESCRIPTION = "android.media.metadata.DISPLAY_DESCRIPTION"
METADATA_KEY_DISPLAY_ICON = "android.media.metadata.DISPLAY_ICON"
METADATA_KEY_DISPLAY_ICON_URI = "android.media.metadata.DISPLAY_ICON_URI"
METADATA_KEY_DISPLAY_SUBTITLE = "android.media.metadata.DISPLAY_SUBTITLE"
METADATA_KEY_DISPLAY_TITLE = "android.media.metadata.DISPLAY_TITLE"
METADATA_KEY_DURATION = "android.media.metadata.DURATION"
METADATA_KEY_GENRE = "android.media.metadata.GENRE"
METADATA_KEY_MEDIA_ID = "android.media.metadata.MEDIA_ID"
METADATA_KEY_NUM_TRACKS = "android.media.metadata.NUM_TRACKS"
METADATA_KEY_RATING = "android.media.metadata.RATING"
METADATA_KEY_TITLE = "android.media.metadata.TITLE"
METADATA_KEY_TRACK_NUMBER = "android.media.metadata.TRACK_NUMBER"
METADATA_KEY_USER_RATING = "android.media.metadata.USER_RATING"
METADATA_KEY_WRITER = "android.media.metadata.WRITER"
METADATA_KEY_YEAR = "android.media.metadata.YEAR"
class Builder(Stub):
"""MediaMetadata.Builder — 元数据构建器"""
def __init__(self):
super().__init__()
self._data: Dict[str, Any] = {}
def putString(self, key: str, value: str) -> "MediaMetadata.Builder":
self._data[key] = value
return self
def putLong(self, key: str, value: int) -> "MediaMetadata.Builder":
self._data[key] = value
return self
def putBitmap(self, key: str, value: Any) -> "MediaMetadata.Builder":
self._data[key] = value
return self
def putText(self, key: str, value: str) -> "MediaMetadata.Builder":
self._data[key] = value
return self
def putRating(self, key: str, value: "Rating") -> "MediaMetadata.Builder":
self._data[key] = value
return self
def build(self) -> "MediaMetadata":
mm = MediaMetadata()
mm._data = dict(self._data)
return mm
def __init__(self):
super().__init__()
self._data: Dict[str, Any] = {}
def getString(self, key: str) -> Optional[str]:
v = self._data.get(key)
return str(v) if v is not None else None
def getLong(self, key: str) -> int:
v = self._data.get(key, 0)
try:
return int(v)
except (ValueError, TypeError):
return 0
def getBitmap(self, key: str) -> Any:
return self._data.get(key)
def getText(self, key: str) -> Optional[str]:
return self.getString(key)
def getDescription(self) -> "MediaDescription":
from .media_browse import MediaDescription
builder = MediaDescription.Builder()
title = self.getString(MediaMetadata.METADATA_KEY_TITLE)
if title:
builder.setTitle(title)
artist = self.getString(MediaMetadata.METADATA_KEY_ARTIST)
if artist:
builder.setSubtitle(artist)
media_id = self.getString(MediaMetadata.METADATA_KEY_MEDIA_ID)
if media_id:
builder.setMediaId(media_id)
return builder.build()
def getRating(self, key: str) -> Optional["Rating"]:
v = self._data.get(key)
return v if isinstance(v, Rating) else None
def getBitmapDescription(self) -> Any:
return None
def containsKey(self, key: str) -> bool:
return key in self._data
def keySet(self) -> Set[str]:
return set(self._data.keys())
def getMediaId(self) -> Optional[str]:
return self.getString(MediaMetadata.METADATA_KEY_MEDIA_ID)
def toString(self) -> str:
title = self.getString(MediaMetadata.METADATA_KEY_TITLE)
return f"MediaMetadata(title={title})"
# ═══════════════════════════════════════════════════════════════
# QueueItem
# ═══════════════════════════════════════════════════════════════
class QueueItem(Stub):
"""QueueItem — 队列项"""
def __init__(self, description: "MediaDescription" = None, queueId: int = 0):
super().__init__()
self._description = description
self._queue_id = queueId
def getDescription(self) -> "MediaDescription":
return self._description
def getQueueId(self) -> int:
return self._queue_id
def toString(self) -> str:
return f"QueueItem(id={self._queue_id}, desc={self._description})"
# ═══════════════════════════════════════════════════════════════
# Rating
# ═══════════════════════════════════════════════════════════════
class Rating(Stub):
"""Rating — 评分"""
RATING_NONE = 0
RATING_HEART = 1
RATING_THUMB_UP_DOWN = 2
RATING_3_STARS = 3
RATING_4_STARS = 4
RATING_5_STARS = 5
RATING_PERCENTAGE = 6
def __init__(self, ratingStyle: int = RATING_NONE):
super().__init__()
self._rating_style = ratingStyle
self._rated = False
self._heart = False
self._thumb_up = False
self._star_rating = 0.0
self._percent_rating = 0.0
@staticmethod
def newHeartRating(hasHeart: bool) -> "Rating":
r = Rating(Rating.RATING_HEART)
r._rated = True
r._heart = hasHeart
return r
@staticmethod
def newThumbRating(thumbUp: bool) -> "Rating":
r = Rating(Rating.RATING_THUMB_UP_DOWN)
r._rated = True
r._thumb_up = thumbUp
return r
@staticmethod
def newStarRating(starRatingStyle: int, starRating: float) -> "Rating":
r = Rating(starRatingStyle)
r._rated = True
r._star_rating = starRating
return r
@staticmethod
def newPercentageRating(percent: float) -> "Rating":
r = Rating(Rating.RATING_PERCENTAGE)
r._rated = True
r._percent_rating = percent
return r
@staticmethod
def newUnratedRating(ratingStyle: int) -> "Rating":
return Rating(ratingStyle)
def isRated(self) -> bool:
return self._rated
def getRatingStyle(self) -> int:
return self._rating_style
def hasHeart(self) -> bool:
return self._heart
def isThumbUp(self) -> bool:
return self._thumb_up
def getStarRating(self) -> float:
return self._star_rating
def getPercentRating(self) -> float:
return self._percent_rating
def toString(self) -> str:
return f"Rating(style={self._rating_style}, rated={self._rated})"
# ═══════════════════════════════════════════════════════════════
# SessionToken
# ═══════════════════════════════════════════════════════════════
class SessionToken(Stub):
"""SessionToken — 会话令牌"""
TYPE_SESSION = 0
def __init__(self, type_: int = TYPE_SESSION):
super().__init__()
self._type = type_
self._binder = None
def getType(self) -> int:
return self._type
def getSessionBinder(self) -> Any:
return self._binder
def toString(self) -> str:
return f"SessionToken(type={self._type})"
# ═══════════════════════════════════════════════════════════════
# __all__
# ═══════════════════════════════════════════════════════════════
__all__ = [
"MediaSession",
"MediaController",
"PlaybackState",
"MediaMetadata",
"QueueItem",
"Rating",
"SessionToken",
]