Repository navigation
Audio Mixer HAL Routing and Connectivity Test Direction
A proposed direction for testing a vendor's com.rdk.hal.audiomixer
implementation: verify that each configured input reaches exactly the mixers
and output ports it is routed to, at the commanded level, and nowhere else.
Applies to interface version 0.3.0.0 (audiomixer/current).
The audio mixer HAL is the routing plane between audio producers (audio sinks, application audio, HDMI/composite inputs) and the physical output ports. A suite that drives the HAL directly isolates the vendor implementation from everything above it: if the plumbing is right here, routing failures higher up are wiring rather than mixer faults.
The suite qualifies the HAL contract, not the SoC. The test matrix is
derived at runtime from what the implementation advertises —
Capabilities.inputs,
getAudioOutputPortIds(),
per-port OutputPortCapabilities
— and every advertised combination must pass. Unadvertised combinations are
skipped with a recorded reason. The only per-platform configuration the suite
accepts is physical rig wiring for the external-stimulus tier.
The suite exercises the routing plane with synthetic stereo PCM markers only. Audio format processing (MS12/DAP, passthrough formats) is a separate conformance area and is not exercised here.
| Interface | Role in this suite |
|---|---|
IAudioMixerManager |
Enumerate mixers (getAudioMixerIds(), getAudioMixer()) |
IAudioMixer |
getCapabilities(), getAudioOutputPortIds(), open()/close(), getInputRouting() readback |
IAudioMixerController |
setInputRouting(), setInputVolume(), setInputVolumeRamp(), lifecycle (start/stop/flush) |
InputRouting |
Routing entry: {AudioSourceType, sourceIndex}
|
AudioSourceType |
AUDIO_SINK, HDMI_INPUT, COMPOSITE_INPUT, APPLICATION_AUDIO
|
IAudioOutputPort / IAudioOutputPortController
|
Per-port state, ENABLED/MUTE/VOLUME properties, capture access |
IAudioCapture / IAudioCaptureListener
|
Observation point: shared-memory PCM tap per output port |
IAudioCapture is obtained per output port via
IAudioOutputPortController.getAudioCapture() and gated by
OutputPortCapabilities.supportsAudioCapture. Where a port advertises
capture, mixer-to-port fan-out is verified in-system; ports without capture
support are verified by physical loopback in the external-stimulus tier.
Each active input carries a unique, machine-detectable marker: a pure tone at
a distinct non-harmonically-related frequency (997 Hz, 1201 Hz, 1499 Hz,
1741 Hz, ...), stereo PCM, 48 kHz, −20 dBFS, generated by the harness.
AUDIO_SINK and APPLICATION_AUDIO markers are injected through the
corresponding com.rdk.hal.audiosink instances; HDMI_INPUT and
COMPOSITE_INPUT markers require external stimulus. The captured output is
analysed with a per-frequency Goertzel detector — ~100 lines of dependency-free
C++, deterministic, CI-friendly.
flowchart LR
subgraph Harness["Test harness"]
GEN["Marker generators<br/>997 Hz / 1201 Hz / 1499 Hz"]
DET["Goertzel detector<br/>per marker frequency"]
end
subgraph HAL["audiomixer HAL"]
IN0["Input 0<br/>AUDIO_SINK 0"]
IN1["Input 1<br/>AUDIO_SINK 1"]
IN2["Input 2<br/>APPLICATION_AUDIO"]
MIX["IAudioMixer<br/>setInputRouting()"]
P0["Output port HDMI"]
P1["Output port SPEAKERS"]
CAP["IAudioCapture<br/>per-port PCM tap"]
end
GEN --> IN0 & IN1 & IN2
IN0 & IN1 & IN2 --> MIX
MIX --> P0 & P1
P0 & P1 --> CAP
CAP --> DET
Four metrics decide pass/fail:
| Metric | Definition | Pass criterion |
|---|---|---|
| Presence | Level of a routed input's marker at the observed output | ≥ −30 dBFS (marker injected at −20 dBFS; margin absorbs mixer headroom scaling) |
| Isolation | Level of every non-routed input's marker at the observed output | ≤ −60 dBFS |
| Level tracking | Measured marker level delta after setInputVolume() / setInputVolumeRamp() / MUTE
|
Delta matches commanded change ±1 dB; MUTE and MixingMode.MUTED drive the marker below −60 dBFS |
| Switch latency | Time from setInputRouting() return to old marker gone and new marker present at the capture point |
Recorded and reported; threshold set per requirement clause, not per SoC |
The presence/isolation pair is the core of the suite: presence proves the commanded route exists; isolation proves no un-commanded route exists. Isolation is measured on every test, not only in dedicated cross-talk cases — every capture window is checked for all markers currently being injected anywhere in the system.
Interface-level tests against the AIDL contract. These run against any implementation, including a reference stub on an x86 simulation.
| ID | Test | Pass criterion |
|---|---|---|
| AMX-T1-001 | Enumerate mixers |
getAudioMixerIds() non-empty; getAudioMixer() non-null for each advertised id, null for others |
| AMX-T1-002 | Capabilities honesty |
getCapabilities().inputs non-empty; each MixerInput declares supportedContentTypes and supportedCodecs
|
| AMX-T1-003 | Open/close lifecycle |
open() returns controller in READY; second open() on same mixer per contract; close() with foreign controller returns false |
| AMX-T1-004 | Routing readback | For every valid InputRouting[] combination derived from capabilities: setInputRouting() returns true and getInputRouting() returns the identical array |
| AMX-T1-005 | Routing rejection | Out-of-range sourceIndex, AudioSourceType not offered by any MixerInput, duplicate entries: setInputRouting() returns false and prior routing is retained |
| AMX-T1-006 | Volume bounds |
setInputVolume() rejects out-of-range inputIndex; getInputVolume() reads back the set value |
| AMX-T1-007 | State machine |
start/stop/flush sequences drive the documented State transitions; event listener receives each transition exactly once |
| AMX-T1-008 | Listener lifecycle | Register/unregister pairs; unregistered listener receives no further events |
| AMX-T1-009 | Secure open |
open(secure=true) honoured only when Capabilities.supportsSecure; capture from a secure mixer is denied or zero-filled per contract |
Markers flowing, observed at the per-port capture tap, on target hardware. The
routing matrix is generated at runtime: every advertised
{input source} x {mixer id} x {capture-capable output port} combination.
| ID | Test | Pass criterion |
|---|---|---|
| AMX-T2-001 | Single route presence | One input routed to one mixer: marker present at every port fed by that mixer, all four metrics pass |
| AMX-T2-002 | Full matrix sweep | Every advertised input x mixer x port combination in turn: presence + isolation on each |
| AMX-T2-003 | Concurrent isolation | Two inputs routed to different mixers simultaneously: each port carries only its own mixer's marker; both isolation floors hold |
| AMX-T2-004 | Multi-input mix | Two inputs routed to the same mixer: both markers present at the mixer's ports at commanded relative levels |
| AMX-T2-005 | Route switch | Routing changed while started: old marker decays below floor, new marker appears; switch latency recorded; no capture gap longer than one buffer period |
| AMX-T2-006 | Volume and ramp |
setInputVolume() steps and setInputVolumeRamp() curves measured against level-tracking criterion; ramp completes within overMs ±1 buffer period |
| AMX-T2-007 | Mixing modes |
MUTED/DUCKED/SOLO/MIXED_OVERRIDE each verified by measured level per mode definition |
| AMX-T2-008 | Port property plumbing | Per-port ENABLED=false and MUTE=true drive that port's marker below floor while other ports are unaffected |
| AMX-T2-009 | Flush and discontinuity |
flush()/signalDiscontinuity() during flow: marker resumes, no stale audio from before the flush appears after it |
| AMX-T2-010 | Soak sweep | AMX-T2-002 repeated for N cycles (default 100): no drift in presence level, no isolation degradation, no underflow/overflow growth (METRIC_UNDERFLOWS/METRIC_OVERFLOWS) |
Only where the marker must cross a physical connector. Rig wiring (which connector loops to which capture device) is the single permitted per-platform configuration input.
| ID | Test | Pass criterion |
|---|---|---|
| AMX-T3-001 | HDMI input routing | External source plays a marker into HDMI_INPUT; routed per AMX-T2-001; presence + isolation at capture-capable ports |
| AMX-T3-002 | Composite input routing | As AMX-T3-001 for COMPOSITE_INPUT where advertised |
| AMX-T3-003 | Physical port verification | For ports with supportsAudioCapture=false: physical loopback (HDMI/SPDIF into an external capture card) confirms presence + isolation at the connector |
- Every test derives its parameter set from runtime capability enumeration. A hard-coded mixer id, port name, or input count anywhere in the suite is a defect in the suite.
- An advertised capability that fails is a HAL compliance failure; there is no per-SoC waiver table or expected-results file.
- Skips are recorded with the capability field that gated them, so the per-SoC report distinguishes "not advertised" from "not run".
- Test signals are harness-generated PCM only; no licensed content, no encoded formats.
-
Property.DEBUG_TAP_ENABLEDmay be used as a supplementary engineering tap during failure triage; pass/fail is decided only at theIAudioCaptureobservation point defined per test.