Cómo conectar un dispositivo de entrada en AAOS

Puedes usar estos mecanismos para reproducir audio en Android:

Cada mecanismo permite la reproducción de audio en Android. Para la reproducción de radio o la reproducción desde dispositivos de entrada, es posible que estas opciones no sean suficientes, aunque cada una podría combinarse con la captura de audio o la clase MediaRecorder para capturar primero el audio y, luego, reproducirlo desde Android. En el caso de las apps del sistema en particular, se puede usar la siguiente información para conectar un dispositivo de entrada a un mezclador de salida en AAOS.

Reproductor de HwAudioSource

HwAudioSource conecta el dispositivo fuente de audio directamente a un mezclador de Android.

Motivaciones

Pueden surgir varias limitaciones cuando se usa un parche de audio de hardware o de dispositivo a dispositivo con Android. Cada opción no puede recibir eventos de teclas multimedia, como PLAY, PAUSE y STOP, y, debido a que evitan la pila de audio de Android, cada una requiere hardware para mezclar el parche en otro audio de Android.

Usa HwAudioSource

HwAudioSource es un nuevo tipo de reproductor diseñado como parche de software. Esto permite que las apps que usan este reproductor reciban eventos de teclas multimedia y que Android mezcle y enrute el flujo de salida.

mHwAudioSource = new HwAudioSource.Builder()
                .setAudioDeviceInfo(AudioDeviceInfo: info)
                .setAudioAttributes(new AudioAttributes.Builder()
                        .setUsage(AudioAttributes.USAGE_MEDIA)
                        .build())
                .build();
mHwAudioSource.play();
mHwAudioSource.stop();

Cambios en la HAL de audio

Con este nuevo reproductor, ten en cuenta estas expectativas para la HAL de audio. Por ejemplo, device/generic/car/emulator/audio/driver/audio_hw.c.

  • adev_create_audio_patch espera que la solicitud establezca un parche de audio desde un dispositivo a un mezclador.

  • adev_open_input_stream espera que audio_source sea AUDIO_SOURCE_FM_TUNER.

  • in_read llena el búfer de audio con datos de audio de radio de transmisión.

Te recomendamos que configures un dispositivo sintonizador con el tipo AUDIO_DEVICE_IN_FM_TUNER en audio_policy_configuration.xml:

<devicePort
    tagName="Tuner_source"
    type="AUDIO_DEVICE_IN_FM_TUNER"
    role="source"
    address="tuner0">
    <profile
        name=""
        format="AUDIO_FORMAT_PCM_16_BIT"
        samplingRates="48000"
        channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
</devicePort>

Con esta configuración del dispositivo, puedes facilitar la búsqueda del dispositivo de entrada de radio FM con AudioManager.getDevices(AudioManager.GET_DEVICES_INPUTS en conjunto con AudioDeviceInfo.TYPE_FM_TUNER.

Crea parches de audio

Puedes crear una conexión de audio entre dos puertos de audio, ya sea un puerto de mezcla o un puerto de dispositivo. Por lo general, un parche de audio del puerto de mezcla al puerto del dispositivo es para la reproducción, mientras que la dirección inversa es para la captura.

Por ejemplo, un parche de audio que enruta muestras de audio desde la fuente FM_TUNER directamente al receptor de medios omite el mezclador de software. Luego, debes usar un mezclador de hardware para mezclar las muestras de audio de Android y FM_TUNER para el receptor. Cuando se crea un parche de audio directamente desde la fuente FM_TUNER al receptor de medios, se deben tener en cuenta los siguientes aspectos:

  • El control de volumen se aplica al receptor de medios y debería afectar tanto el audio de Android como el de FM_TUNER.

  • Los usuarios pueden cambiar entre el audio de Android y el de FM_TUNER con un simple cambio de app (no es necesario elegir una fuente de medios explícita).

Es posible que las implementaciones en automóviles también deban crear un parche de audio entre dos puertos del dispositivo. Para ello, primero debes declarar los puertos del dispositivo y las posibles rutas en audio_policy_configuration.xml y, luego, asociar los puertos de mezcla con los puertos del dispositivo.

Configuración de ejemplo

Consulta esta configuración de muestra, device/generic/car/emulator/audio/audio_policy_configuration.xml.

<audioPolicyConfiguration>
    <modules>
        <module name="primary" halVersion="3.0">
            <attachedDevices>
                <item>bus0_media_out</item>
                <item>bus1_audio_patch_test_in</item>
            </attachedDevices>
            <mixPorts>
                <mixPort name="mixport_bus0_media_out" role="source"
                        flags="AUDIO_OUTPUT_FLAG_PRIMARY">
                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                            samplingRates="48000"
                            channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
                </mixPort>
                <mixPort name="mixport_audio_patch_in" role="sink">
                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                           samplingRates="48000"
                           channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
                </mixPort>
            </mixPorts>
            <devicePorts>
                <devicePort tagName="bus0_media_out" role="sink" type="AUDIO_DEVICE_OUT_BUS"
                        address="bus0_media_out">
                    <profile balance="" format="AUDIO_FORMAT_PCM_16_BIT"
                            samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
                    <gains>
                        <gain name="" mode="AUDIO_GAIN_MODE_JOINT"
                                minValueMB="-8400" maxValueMB="4000" defaultValueMB="0" stepValueMB="100"/>
                    </gains>
                </devicePort>
                <devicePort tagName="bus1_audio_patch_test_in" type="AUDIO_DEVICE_IN_BUS" role="source"
                        address="bus1_audio_patch_test_in">
                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                            samplingRates="48000" channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
                    <gains>
                        <gain name="" mode="AUDIO_GAIN_MODE_JOINT"
                                minValueMB="-8400" maxValueMB="4000" defaultValueMB="0" stepValueMB="100"/>
                    </gains>
                </devicePort>
            </devicePorts>
            <routes>
                <route type="mix" sink="bus0_media_out" sources="mixport_bus0_media_out,bus1_audio_patch_test_in"/>
                <route type="mix" sink="mixport_audio_patch_in" sources="bus1_audio_patch_test_in"/>
            </routes>
        </module>
    </modules>
</audioPolicyConfiguration>

API del controlador de audio

Puedes usar getExternalSources() para recuperar una lista de fuentes disponibles (identificadas por dirección) y, luego, crear parches de audio entre estas fuentes y los puertos de receptor según los usos de audio. Los puntos de entrada correspondientes en el HAL de audio aparecen en IDevice.hal:

Interface IDevice {
...
/
*   Creates an audio patch between several source and sink ports.  The handle
*   is allocated by the HAL and must be unique for this audio HAL module.
*
*   @param sources patch sources.
*   @param sinks patch sinks.
*   @return retval operation completion status.
*   @return patch created patch handle.
*/
createAudioPatch(vec<AudioPortConfig> sources, vec<AudioPortConfig> sinks)
       generates (Result retval, AudioPatchHandle patch);

*   Release an audio patch.
*
*   @param patch patch handle.
*   @return retval operation completion status.
*/
releaseAudioPatch(AudioPatchHandle patch) generates (Result retval);
...
}

Radio

Cuando compiles una app de radio, te recomendamos que uses HwAudioSource, ya que controla la creación del parche y una sesión multimedia para controlar los eventos de las claves de medios. Se pueden crear varias fuentes de audio para los mismos atributos de audio y fuente. Es posible tener una para el uso normal de la radio y otra para los anuncios de tráfico.

Si se graba el FM_TUNER, en Android 11, el permiso para hacerlo se cambió a android.permission.CAPTURE_AUDIO_OUTPUT. Ya no pasa por la verificación de permisos OP_RECORD_AUDIO, que solo se aplica a los micrófonos. Esto no debería afectar a las apps, ya que FM_TUNER ya requiere el permiso SYSTEM_API para acceder.

Consulta Implementa la radio para obtener detalles sobre cómo compilar una app de radio.