Files
mg4/app/src/test/java/com/evsuite/abrp/NowPlayingTest.java
T
nilsandClaude Opus 5.5 91283093f5 App 2.45.0: now playing on the Overview
NowPlayingWatcher follows the head unit's media sessions (listening
only, never connecting to a player); NowPlaying picks what plays and
cleans the text. Tiles shows source, title, artist, cover and progress
under the battery; Halloween carves title and artist into the hill.
Settings: "Show what's playing", on by default. Nothing is logged or
sent.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LhzAVaUyqcw5PkGjz4mWW6
2026-11-02 14:03:26 +01:00

139 lines
6.2 KiB
Java

package com.evsuite.abrp;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.util.Arrays;
import java.util.Collections;
import org.junit.Test;
public class NowPlayingTest {
private static NowPlaying.Session session(String pkg, int state, String title, String artist, long updatedAt) {
NowPlaying.Session s = new NowPlaying.Session();
s.packageName = pkg;
s.state = state;
s.title = title;
s.artist = artist;
s.positionUpdatedAt = updatedAt;
return s;
}
@Test
public void nothingToShow() {
assertNull(NowPlaying.pick(null));
assertNull(NowPlaying.pick(Collections.emptyList()));
// Bluetooth's empty session after the phone stopped, and one that only connects.
assertNull(NowPlaying.pick(Arrays.asList(
session("com.android.bluetooth", 1, "", "", 5),
session("com.android.car.radio", 8, "Radio", null, 6),
session("com.android.bluetooth", NowPlaying.STATE_PLAYING, " ", null, 7))));
}
@Test
public void whatPlaysWinsOverWhatIsPaused() {
// As on the car on 2026-10-28: CarPlay paused, Bluetooth playing.
NowPlaying.Track t = NowPlaying.pick(Arrays.asList(
session("com.allgo.remoteui.mediabrowserservice", NowPlaying.STATE_PAUSED, "A Mix", "Bass Bangers", 900),
session("com.android.bluetooth", NowPlaying.STATE_PLAYING, "Paramount", "Mark Petrie & Andrew Prahlow", 100)));
assertEquals(NowPlaying.Source.BLUETOOTH, t.source);
assertEquals("Paramount", t.title);
assertEquals("Mark Petrie & Andrew Prahlow", t.subtitle);
assertTrue(t.playing);
}
@Test
public void ofTwoPlayingTheNewerWins() {
NowPlaying.Track t = NowPlaying.pick(Arrays.asList(
session("com.android.bluetooth", NowPlaying.STATE_PLAYING, "Old", null, 100),
session("com.allgo.remoteui.mediabrowserservice", NowPlaying.STATE_BUFFERING, "New", null, 200)));
assertEquals(NowPlaying.Source.CARPLAY, t.source);
assertEquals("New", t.title);
}
@Test
public void withNothingPlayingThePausedOneShows() {
NowPlaying.Track t = NowPlaying.pick(Arrays.asList(
session("com.android.bluetooth", NowPlaying.STATE_PAUSED, "Earlier", null, 100),
session("com.allgo.remoteui.mediabrowserservice", NowPlaying.STATE_PAUSED, "Later", null, 300)));
assertEquals("Later", t.title);
assertFalse(t.playing);
}
@Test
public void theRadioShowsItsTextWithTheStationBelow() {
NowPlaying.Track t = NowPlaying.pick(Collections.singletonList(
session("com.saicmotor.radio", NowPlaying.STATE_PLAYING, "Brillux Radio", "BLIND MELON - NO RAIN", 1)));
assertEquals(NowPlaying.Source.RADIO, t.source);
assertEquals("BLIND MELON - NO RAIN", t.title);
assertEquals("Brillux Radio", t.subtitle);
NowPlaying.Track station = NowPlaying.pick(Collections.singletonList(
session("com.saicmotor.radio", NowPlaying.STATE_PLAYING, "Brillux Radio", "", 1)));
assertEquals("Brillux Radio", station.title);
assertNull(station.subtitle);
assertEquals(-1f, station.progressAt(5), 0f);
}
@Test
public void textIsCleaned() {
assertEquals("A Letter to the Past (A Seasonal Feels Mix) Ft. Porter Robinson & Friends By SAINT",
NowPlaying.clean("A Letter to the Past (A Seasonal Feels Mix) Ft. Porter Robinson & Friends By SAINT [X4nayMeMBuQ]"));
assertEquals("Live [Remastered 2011]", NowPlaying.clean("Live [Remastered 2011]"));
assertEquals("two lines", NowPlaying.clean(" two\n lines "));
assertNull(NowPlaying.clean(" "));
assertNull(NowPlaying.clean(null));
StringBuilder longText = new StringBuilder();
for (int i = 0; i < 300; i++) longText.append('x');
assertEquals(200, NowPlaying.clean(longText.toString()).length());
}
@Test
public void onlyAnArtistStillShows() {
NowPlaying.Track t = NowPlaying.pick(Collections.singletonList(
session("com.example.player", NowPlaying.STATE_PLAYING, null, "Someone", 1)));
assertEquals(NowPlaying.Source.OTHER, t.source);
assertEquals("Someone", t.title);
assertNull(t.subtitle);
}
@Test
public void thePositionRunsOnWhilePlayingAndStopsAtTheEnd() {
NowPlaying.Session s = session("com.android.bluetooth", NowPlaying.STATE_PLAYING, "Paramount", "M", 10_000);
s.positionMs = 3_000;
s.durationMs = 215_000;
NowPlaying.Track t = NowPlaying.pick(Collections.singletonList(s));
assertEquals(3_000, t.positionAt(10_000));
assertEquals(8_000, t.positionAt(15_000));
assertEquals(215_000, t.positionAt(10_000_000));
assertEquals(1f, t.progressAt(10_000_000), 0f);
assertEquals(8_000 / 215_000f, t.progressAt(15_000), 1e-6f);
}
@Test
public void aPausedPositionStaysPut() {
NowPlaying.Session s = session("com.android.bluetooth", NowPlaying.STATE_PAUSED, "Paramount", null, 10_000);
s.positionMs = 3_000;
s.durationMs = 215_000;
assertEquals(3_000, NowPlaying.pick(Collections.singletonList(s)).positionAt(99_000));
}
@Test
public void noPositionNoBar() {
NowPlaying.Session s = session("com.android.bluetooth", NowPlaying.STATE_PLAYING, "Paramount", null, 10_000);
s.durationMs = 215_000;
assertEquals(-1f, NowPlaying.pick(Collections.singletonList(s)).progressAt(20_000), 0f);
}
@Test
public void sourcesAreKnownByTheirApps() {
assertEquals(NowPlaying.Source.BLUETOOTH, NowPlaying.source("com.android.bluetooth"));
assertEquals(NowPlaying.Source.CARPLAY, NowPlaying.source("com.allgo.remoteui.mediabrowserservice"));
assertEquals(NowPlaying.Source.RADIO, NowPlaying.source("com.saicmotor.radio"));
assertEquals(NowPlaying.Source.OTHER, NowPlaying.source("com.android.music"));
assertEquals(NowPlaying.Source.OTHER, NowPlaying.source(null));
}
}