fix(eq): stop the phone's FM sink from posing as the active output
Regression from the previous commit. Ranking every AudioDeviceInfo type this
build does not name individually ABOVE the built-in speaker was meant to let
a car stereo on LE Audio or an automotive bus win. It also promoted the
internal sinks a phone exposes permanently: on the Xiaomi test device
AudioManager reports TYPE_FM (14) as an output, so getActiveAudioDevice
picked it over the real speaker with nothing connected at all. Confirmed on
device:
audio_devices.onListen -> {id=other:14:4, type=14, name=2412DPC0AG}
It then reached Dart under an `other:14:4` id whose type is neither the base
speaker nor a known one, slipped past the collision guard and had a preset
row persisted for it -- reinstating the exact symptom this series set out to
kill: a permanent green active-output dot on a device that was not connected.
Replace the deny-by-omission ranking with an explicit allow list of outputs a
user actually connects. The built-in speaker sits below all of them and above
everything else, so any sink that physically exists but is never where media
plays (TYPE_FM, TYPE_BUILTIN_SPEAKER_SAFE, telephony, remote submix) can no
longer be selected. A one-time purge clears the `other:` rows the bad build
persisted; genuine ones re-register on their next connection.
Fix the USB type constant while here: TYPE_USB_HEADSET is 22, not 14, and 14
is TYPE_FM. The Kotlin USB branch hardcoded 14 and the Dart type table
mirrored the same mistake, so the two cancelled out for real USB headsets
while making a phone's own FM sink decode as USB audio. Both now use 22.
Verified with javap against android.jar (android-36) rather than trusting the
comment that introduced the error.
This commit is contained in:
@@ -22,6 +22,13 @@ const prefijoPlaceholderBtName = 'bt_a2dp:name:';
|
||||
/// entry that then marked the wrong device as active forever.
|
||||
const idAltavozInterno = 'builtin_speaker';
|
||||
|
||||
/// Id prefix for outputs the native layer does not name individually
|
||||
/// (`other:<AudioDeviceInfo type>:<address>`): LE Audio stereos, car buses,
|
||||
/// hearing aids, docks. Kept distinct from every other id namespace so such a
|
||||
/// device can never collide with [idAltavozInterno], and so a bad batch of them
|
||||
/// can be purged wholesale.
|
||||
const prefijoDispositivoOtro = 'other:';
|
||||
|
||||
/// Abstract service for audio device detection.
|
||||
///
|
||||
/// Implementations:
|
||||
@@ -79,7 +86,11 @@ abstract class ServicioDispositivoAudio {
|
||||
/// 2 → altavozInterno (builtin_speaker)
|
||||
/// 3 → auricularesCable (wired_headset)
|
||||
/// 8 → bluetoothA2dp (`bt_a2dp:<MAC>`)
|
||||
/// 14 → usbAudio (`usb_headset:<address>`)
|
||||
/// 22 → usbAudio (`usb_headset:<address>`)
|
||||
///
|
||||
/// Values match `AudioDeviceInfo.TYPE_*`. Note 22, NOT 14: type 14 is
|
||||
/// `TYPE_FM`, an output plenty of phones expose permanently, and mapping it to
|
||||
/// USB audio made a phone's own FM sink look like a connected headset.
|
||||
class ServicioDispositivoAudioReal extends ServicioDispositivoAudio {
|
||||
static const _channelName = 'pluriwave/audio_devices';
|
||||
|
||||
@@ -189,7 +200,7 @@ class ServicioDispositivoAudioReal extends ServicioDispositivoAudio {
|
||||
return TipoDispositivo.auricularesCable;
|
||||
case 8:
|
||||
return TipoDispositivo.bluetoothA2dp;
|
||||
case 14:
|
||||
case 22:
|
||||
return TipoDispositivo.usbAudio;
|
||||
default:
|
||||
return TipoDispositivo.desconocido;
|
||||
|
||||
Reference in New Issue
Block a user