Conectar um dispositivo de entrada no AAOS

Você pode usar estes mecanismos para reproduzir áudio no Android:

Cada mecanismo permite a reprodução de áudio no Android. Para reprodução de rádio ou de dispositivos de entrada, essas opções podem não ser suficientes, embora cada uma possa ser combinada com a captura de áudio ou a classe MediaRecorder para capturar o áudio primeiro e depois reproduzi-lo no Android. Para apps do sistema em particular, as informações a seguir podem ser usadas para conectar um dispositivo de entrada a um mixer de saída no AAOS.

Player HwAudioSource

O HwAudioSource conecta o dispositivo de origem de áudio diretamente a um mixer do Android.

Motivações

Várias limitações podem surgir ao usar um patch de áudio de dispositivo para dispositivo ou de hardware com o Android. Cada opção não pode receber eventos de tecla de mídia, como PLAY, PAUSE e STOP. Como elas contornam a pilha de áudio do Android, cada uma exige hardwares para misturar o patch em outro áudio do Android.

Usar HwAudioSource

HwAudioSource é um novo tipo de player projetado como um patch de software. Isso permite que os apps que usam esse player recebam eventos de chave de mídia e que o stream de saída seja misturado e roteado pelo Android.

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

Mudanças na HAL de áudio

Com esse novo player, considere estas expectativas para o HAL de áudio. Por exemplo, device/generic/car/emulator/audio/driver/audio_hw.c.

  • O adev_create_audio_patch espera que a solicitação estabeleça um patch de áudio de um dispositivo para um mixer.

  • O adev_open_input_stream espera que o audio_source seja AUDIO_SOURCE_FM_TUNER.

  • in_read preenche o buffer de áudio com dados de áudio de transmissão de rádio.

Recomendamos que você configure um dispositivo de sintonizador com o tipo AUDIO_DEVICE_IN_FM_TUNER em 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>

Com essa configuração, é possível encontrar o dispositivo de entrada de rádio FM usando AudioManager.getDevices(AudioManager.GET_DEVICES_INPUTS em conjunto com AudioDeviceInfo.TYPE_FM_TUNER.

Criar patches de áudio

É possível criar um patch de áudio entre duas portas de áudio, seja uma porta de mixagem ou uma porta de dispositivo. Normalmente, um patch de áudio da porta de mix para a porta do dispositivo é para reprodução, enquanto a direção reversa é para captura.

Por exemplo, um patch de áudio que encaminha amostras de áudio da fonte FM_TUNER diretamente para o sink de mídia ignora o mixer de software. Em seguida, use um misturador de hardware para misturar as amostras de áudio do Android e do FM_TUNER para o sink. Ao criar um patch de áudio diretamente da fonte FM_TUNER para o destino de mídia:

  • O controle de volume se aplica ao sink de mídia e precisa afetar o áudio do Android e do FM_TUNER.

  • Os usuários podem alternar entre o Android e o áudio FM_TUNER com um simples interruptor de app. Não é necessário escolher uma fonte de mídia explícita.

As implementações automotivas também podem precisar criar um patch de áudio entre duas portas do dispositivo. Para fazer isso, primeiro declare as portas do dispositivo e as rotas possíveis em audio_policy_configuration.xml e, em seguida, associe as mixports às portas do dispositivo.

Exemplo de configuração

Consulte este exemplo de configuração, 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 Audio Driver

É possível usar getExternalSources() para extrair uma lista de fontes disponíveis (identificadas pelo endereço) e criar patches de áudio entre essas fontes e as portas de destino por usos de áudio. Os pontos de entrada correspondentes no HAL de áudio são exibidos em 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);
...
}

Sintonizador de rádio

Ao criar um app de rádio, recomendamos usar o HwAudioSource, que processa a criação do patch e uma sessão de mídia para processar eventos de chave de mídia. Várias fontes de áudio podem ser criadas para a mesma origem e atributos de áudio. É possível ter um para uso regular do rádio e outro para avisos de trânsito.

Se a FM_TUNER for gravada, no Android 11, a permissão para fazer isso será alterada para android.permission.CAPTURE_AUDIO_OUTPUT. Ele não passa mais pela verificação de permissão OP_RECORD_AUDIO, que se aplica apenas a microfones. Isso não afeta os apps, já que FM_TUNER já exige a permissão SYSTEM_API para acesso.

Consulte Implementar rádio para saber mais sobre como criar um app de rádio.