fix(media_player): privacy bare-app identity outranks the channel-title fallback in the foreground tier (F3)

This commit is contained in:
James Mackay committed 2026-10-08 10:52:24 +01:00
1 parent 392553ee26
commit 3b8e97fe5b
2 files changed
+35 -2

No files matched your search

@@ -652,14 +652,16 @@ class NvidiaShieldMediaPlayer(MediaPlayerEntity):
state = "playing" if info.playing else "paused" state = "playing" if info.playing else "paused"
# Privacy mode: identity stays the app, never the media title # Privacy mode: identity stays the app, never the media title
title = None if not self._adb_store_info else info.title title = None if not self._adb_store_info else info.title
if title is None and not self._adb_store_info:
# F3: privacy mode first — identity stays the app, so neither the
# channel number nor the media title can leak as the identity.
title = self.app_name or self.app_id or foreground
if title is None and self._last_channel and ( if title is None and self._last_channel and (
# F1: the channel number belongs to the channel app only — never # F1: the channel number belongs to the channel app only — never
# leak it to the launcher or another foreground app. # leak it to the launcher or another foreground app.
foreground == TIVIMATE_PACKAGE or foreground in manager.audio_playback foreground == TIVIMATE_PACKAGE or foreground in manager.audio_playback
): ):
title = self._last_channel title = self._last_channel
if title is None and not self._adb_store_info:
title = self.app_name or self.app_id or foreground
if title is None and foreground in manager.audio_playback: if title is None and foreground in manager.audio_playback:
# E hint (zero round-trip cost): audio was recently played # E hint (zero round-trip cost): audio was recently played
title = "Media recently active" title = "Media recently active"
+31
View File
@@ -517,6 +517,37 @@ class TestChannelLeakGuard:
assert np["title"] == "205" assert np["title"] == "205"
class TestPrivacyOrdering:
"""F3: privacy mode outranks the channel fallback — identity stays the app."""
async def test_channel_number_never_leaks_in_privacy_mode(self, modules):
player, manager = _ladder_player(modules, foreground=TIVIMATE_PACKAGE)
player._entry.options["adb_store_app_info"] = False # privacy on
player._last_channel = "101"
np = player._get_app_now_playing()
assert np["title"] == TIVIMATE_PACKAGE # app identity, not the channel
assert np["title"] != "101"
async def test_channel_number_never_leaks_in_privacy_mode_with_last_known(self, modules):
from nsh.ha_adb_common import MediaSessionInfo
player, manager = _ladder_player(modules, foreground=TIVIMATE_PACKAGE)
player._entry.options["adb_store_app_info"] = False
manager._clock = lambda: 0.0
info = MediaSessionInfo(
package=TIVIMATE_PACKAGE, playing=True, title="Sky News"
)
manager._last_known[TIVIMATE_PACKAGE] = (info, 0.0)
player._last_channel = "101"
np = player._get_app_now_playing()
assert np["state"] == "playing" # playback truth survives privacy
assert np["title"] == TIVIMATE_PACKAGE # but identity stays the app
class TestVolumeAndPowerLadder: class TestVolumeAndPowerLadder:
async def test_volume_readout_from_protocol_push(self, modules): async def test_volume_readout_from_protocol_push(self, modules):
player, served, _intents = make_player(modules) player, served, _intents = make_player(modules)