/* Every browse the media service answered, as `LibraryBridge` logged it — * one line per node, in the order the browser asked for them. * * Round fifty put the car's browse tree behind a read-only SQLite * connection in a process with NO Activity, no Tauri and no WebView, which * is the whole point of it: the tree has to be there before the app is. * That also means there is no screen to read it back from and no page to * ask, so logcat is the only place on the device this exists at all. `n`, * `br`, `pl`, `uniq`, `titled`, `art` and `fail` are the service's own * count of what it handed the browser; `ms` is measured inside the Rust * call and `hop` around the whole JNI round trip, so a gap between the two * is the bridge rather than the database. `note=` goes LAST because a * sqlite message may hold anything, spaces and `=` included. * * A line that does not parse is simply not a row here, and every check * below fails on a row that is MISSING rather than on a sentinel — which * is why each of them names the node it wanted. */ function autoNodes() { try { const out = adb("logcat", "-d", "-s", "SoulStream:D").toString(); const rows = []; for (const line of out.split(/\r?\n/)) { const m = line.match(/auto node=(\S+) n=(-?\d+) br=(-?\d+) pl=(-?\d+) uniq=(-?\d+) titled=(-?\d+) art=(-?\d+) fail=(-?\d+) lim=(-?\d+) open=(\S+) ms=(-?\d+) hop=(-?\d+) kinds=(\S*) note=(.*)$/); if (!m) continue; rows.push({ node: m[1], n: +m[2], br: +m[3], pl: +m[4], uniq: +m[5], titled: +m[6], art: +m[7], fail: +m[8], lim: +m[9], open: m[10], ms: +m[11], hop: +m[12], kinds: m[13], note: m[14].trim(), }); } return rows; } catch { return []; } }