feat(media_session): map Android PlaybackState 6 to buffering (t55)
The media session parser only understood states 2 (paused) and 3 (playing), so a session refilling its buffer (Android state 6, which the Shield's own ExoPlayer/MediaSession sessions report exactly like stock Android) read as "idle" or vanished into the foreground tier. MediaSessionInfo gains an independent `buffering` flag (playing/paused/ buffering are now three flags off one integer), the session sort puts buffering right behind playing — it is mid-playback, so it outranks a paused session when the ladder picks one — and the running-apps enrichment names a buffering live/last-known session "buffering" instead of falling into "idle". The MediaPlayerState stub gains BUFFERING and STANDBY so an in-suite reference to a member real HA does not have fails here (real HA 2026.10 exposes off/on/idle/playing/paused/standby/buffering).
This commit is contained in:
1 parent
49bc23ae34
commit
07682ff082
4 files changed
+122
-9
No files matched your search
@@ -17,6 +17,12 @@ class MediaSessionInfo:
|
||||
**device uptime-ms** timestamp (verified on Shield Android 11, R9), not a
|
||||
wallclock value. Use :meth:`position_at_uptime` with the device's current
|
||||
uptime to extrapolate the live position.
|
||||
|
||||
``playing``/``paused``/``buffering`` are independent flags mapped from the
|
||||
Android PlaybackState integer: 2 = paused, 3 = playing, 6 = buffering
|
||||
(t55). The Shield's own ExoPlayer/MediaSession sessions report state 6
|
||||
while buffering just as stock Android does, so no vendor-specific state
|
||||
integer is treated as buffering.
|
||||
"""
|
||||
|
||||
title: str | None = None
|
||||
@@ -25,6 +31,7 @@ class MediaSessionInfo:
|
||||
package: str | None = None
|
||||
playing: bool = False
|
||||
paused: bool = False
|
||||
buffering: bool = False
|
||||
position: float | None = None
|
||||
speed: float | None = None
|
||||
updated: int | None = None
|
||||
@@ -81,7 +88,8 @@ def parse_all_media_sessions(dump: str) -> list[MediaSessionInfo]:
|
||||
"""Parse `dumpsys media_session` output for ALL active media sessions.
|
||||
|
||||
Returns a list of every active session that has metadata or a known
|
||||
playback state, sorted: playing first, then paused, then others.
|
||||
playback state, sorted: playing first, then buffering, then paused, then
|
||||
others (t55).
|
||||
"""
|
||||
if not dump:
|
||||
return []
|
||||
@@ -89,7 +97,8 @@ def parse_all_media_sessions(dump: str) -> list[MediaSessionInfo]:
|
||||
sessions: list[MediaSessionInfo] = []
|
||||
current_pkg: str | None = None
|
||||
in_active = False
|
||||
current_state = 0 # 0=unknown, 2=paused, 3=playing
|
||||
# Android PlaybackState: 0=unknown, 2=paused, 3=playing, 6=buffering
|
||||
current_state = 0
|
||||
current_position: float | None = None
|
||||
current_speed: float | None = None
|
||||
current_updated: int | None = None
|
||||
@@ -138,6 +147,7 @@ def parse_all_media_sessions(dump: str) -> list[MediaSessionInfo]:
|
||||
info = MediaSessionInfo()
|
||||
info.package = current_pkg
|
||||
info.playing = current_state == 3
|
||||
info.buffering = current_state == 6
|
||||
info.paused = current_state == 2
|
||||
info.position = current_position
|
||||
info.speed = current_speed
|
||||
@@ -158,13 +168,16 @@ def parse_all_media_sessions(dump: str) -> list[MediaSessionInfo]:
|
||||
current_meta.package = current_pkg
|
||||
sessions.append(current_meta)
|
||||
|
||||
# Sort: playing first, then paused, then others
|
||||
# Sort: playing first, then buffering (mid-playback), then paused, then
|
||||
# others — a buffering session outranks a paused one (t55).
|
||||
def sort_key(s: MediaSessionInfo) -> int:
|
||||
if s.playing:
|
||||
return 0
|
||||
if s.paused:
|
||||
if s.buffering:
|
||||
return 1
|
||||
return 2
|
||||
if s.paused:
|
||||
return 2
|
||||
return 3
|
||||
|
||||
sessions.sort(key=sort_key)
|
||||
return sessions
|
||||
@@ -206,8 +219,9 @@ def parse_media_session(
|
||||
Returns the best match from all active sessions:
|
||||
1. The session whose package matches the foreground app (if provided)
|
||||
2. The session that is currently playing (state=3)
|
||||
3. The session that is paused (state=2)
|
||||
4. Any active session with metadata
|
||||
3. The session that is buffering (state=6)
|
||||
4. The session that is paused (state=2)
|
||||
5. Any active session with metadata
|
||||
"""
|
||||
sessions = parse_all_media_sessions(dump)
|
||||
if not sessions:
|
||||
@@ -218,6 +232,5 @@ def parse_media_session(
|
||||
for s in sessions:
|
||||
if s.package == foreground_package:
|
||||
return s
|
||||
|
||||
# Already sorted: playing > paused > other
|
||||
# Already sorted: playing > buffering > paused > other
|
||||
return sessions[0]
|
||||
@@ -51,8 +51,11 @@ def running_apps_from_tasks(
|
||||
if session:
|
||||
if session.playing:
|
||||
app["state"] = "playing"
|
||||
elif session.buffering:
|
||||
app["state"] = "buffering"
|
||||
elif session.paused:
|
||||
app["state"] = "paused"
|
||||
app["state"] = "paused"
|
||||
else:
|
||||
app["state"] = "idle"
|
||||
if session.title:
|
||||
@@ -66,6 +69,8 @@ def running_apps_from_tasks(
|
||||
if cached is not None:
|
||||
if cached.playing:
|
||||
app["last_known_state"] = "playing"
|
||||
elif cached.buffering:
|
||||
app["last_known_state"] = "buffering"
|
||||
elif cached.paused:
|
||||
app["last_known_state"] = "paused"
|
||||
if cached.title:
|
||||
|
||||
Reference in new issue
Block a user