t66: app names on a device that exposes none

The reported Shield names no app: `pm dump com.netflix.ninja` is ~2241 lines of
dumpsys and grep for `application-label` over the whole capture finds nothing.
The probe shipped `| head -300`, which cut the dump BEFORE the package section,
so "no label" was a truncation artefact; the sweep then named every app after
its own package id, and the apps editor pre-filled the `pkg=pkg` row the user
read as a bug.

  * the probe greps ON THE DEVICE for the three shapes Android prints
    (`application-label`, `nonLocalizedLabel`, `labelRes`); a quoted value is a
    name, `null` and a resource id are not. The dump is never truncated.
  * after APP_LABEL_PROBE_LIMIT consecutive "ran, no label" answers the device
    is taken at its word: the sweep stops spending a shell per package
    (APP_LABEL_TTL expiry re-checks, and a package whose probe FAILED still owes
    its retry — t57 UNIT 0 survives, driven by the app on screen).
  * ONE precedence chain in `ha_adb_common/app_label.resolve_package_name`, used
    by the media player, the Current App sensor, the discovery table, the source
    list and the apps editor: user map > device label > curated map > package id
    (the id shown ONCE, `name` empty when nothing names the app).
  * the curated table covers the user's 21 apps (community-maintained, not
    device truth) and the Configure row says when the device named nothing.
  * the real device shape is a test fixture (trimmed, and marked as such in the
    file: the raw capture is not in the repo) pinning that no label is
    extracted, that the probe count is bounded, and that `Netflix` surfaces.

Also drops the dead `ATTR_MEDIA_DAG_NOW_PLAYING` re-exports left by the t65
flattening and updates the RESEARCH_SHIELD now-playing note to the flat names.

No real Shield was available: the fetch/burst behaviour is exercised against the
documented Android output and the trimmed reproduction of the reported capture.
This commit is contained in:
James Mackay committed 2026-10-12 10:54:38 +01:00
1 parent f29f62ddae
commit 7b32de789a
16 files changed
+973 -176

No files matched your search

+48 -4
View File
@@ -3,7 +3,6 @@
# Re-export shared Media DAG constants
from .ha_adb_common.const import ( # noqa: F401
ATTR_MEDIA_DAG_JELLYFIN_ENTITY,
ATTR_MEDIA_DAG_NOW_PLAYING,
ATTR_MEDIA_DAG_RECEIVER_ENTITY,
ATTR_MEDIA_DAG_RECEIVER_INPUT,
ATTR_MEDIA_DAG_ROLE,
@@ -128,6 +127,26 @@ APP_LABEL_TTL = 24 * 3600
# unlikely to collide with a manifest line.
APP_LABEL_EXIT_MARKER = "__NSH_EXIT:"
# t66: the label candidates searched FOR ON THE DEVICE. A real `pm dump` on the
# user's Shield is ~2241 lines of dumpsys (package + activity + meminfo +
# procstats + usagestats + batterystats), and the old fetch shipped
# ``| head -300`` — which cut before the package sections even appeared, so the
# negative was a truncation artefact rather than an answer. Searching on-device
# keeps the wire small AND the answer honest: these are the three shapes Android
# prints for an app's label (see ha_adb_common/app_label.py for what counts as a
# name in each).
APP_LABEL_GREP_SHAPES = "application-label|nonLocalizedLabel|labelRes"
# t66: how many label probes may come back "ran, no label" IN A ROW before the
# device is treated as one that exposes no labels at all (this user's Shield).
# One label-less package is ordinary (system/OEM packages often have none), so a
# single miss proves nothing — but a run of them means the whole firmware keeps
# its labels in resources we cannot read, and every further ``pm dump`` per
# package is a shell spent on a question already answered. The conclusion expires
# with APP_LABEL_TTL so a device change is noticed within a day, and any label
# found anywhere resets the run.
APP_LABEL_PROBE_LIMIT = 5
# P4-2a adb_command service: rawADB shell on this entry — OFF by default
# (same security posture as the core androidtv integration).
CONF_ADB_COMMAND_ENABLED = "adb_command_enabled"
@@ -142,13 +161,38 @@ CONF_LOGCAT_EVENTS = "logcat_events"
# re-stamped (repeat suppression).
LOGCAT_SUPPRESS_WINDOW = 15.0
# P4-2c BrowseMedia app directory fallback when the options map is empty
# (curated; the packages are the plan's reference apps).
# P4-2c/t66: the curated package -> name table. It is BOTH the BrowseMedia/source
# directory fallback and the third tier of the app-name chain (after the user's
# own map and a device label, before the raw package id) — on a Shield whose
# `pm dump` carries no label at all it is the answer that makes names work.
#
# It is a community-maintained convenience, NOT device truth: package ids are
# stable, display names change with vendors and app updates, and an app this
# table has never heard of falls back to its package id (shown once). Users
# override any entry in Configure > Apps, and that edit always wins. Adding a row
# is deliberately trivial — keep the ids sorted so the diff stays reviewable.
DEFAULT_APP_DIRECTORY = {
"ar.tvplayer.tv": "TiviMate",
"be.digitalia.mediasession2mqtt": "MediaSession2MQTT",
"com.amazon.amazonvideo.livingroom": "Prime Video",
"com.esaba.downloader": "Downloader",
"com.github.damontecres.wholphin": "Wholphin",
"com.netflix.ninja": "Netflix",
"com.google.android.sambadocumentsprovider": "Samba (SMB)",
"com.google.android.speech.pumpkin": "Google Speech Services",
"com.google.android.tts": "Speech Services by Google",
"com.google.android.tvlauncher": "Google TV launcher",
"com.google.android.youtube.tv": "YouTube",
"com.hyperion.grabber": "Hyperion Grabber",
"com.lonelycatgames.Xplore": "X-plore File Manager",
"com.nendo.argosy": "Argosy",
"com.netflix.ninja": "Netflix",
"com.plexapp.mediaserver.smb": "Plex Media Server",
"com.retroarch": "RetroArch",
"com.spocky.projengmenu": "Projectivy Launcher",
"dev.jdtech.jellyfin": "Findroid",
"dev.trooped.tvquickbars": "TV Quick Actions",
"flar2.homebutton": "Button Mapper",
"tv.pluto.android": "Pluto TV",
}
# t57: best-effort icon per discovered app. `pm dump` does NOT expose the