Lo que se requiere para que Android utilice un nuevo Audio HAL

Estoy escribiendo un nuevo Android Audio HAL, para permitir que mi aplicación suministre audio a otras aplicaciones, para permitir que mi entrada de micrófono remoto de mano llegue a la aplicación de Google. Esencialmente, un cable de audio virtual.

Es un trabajo en progreso. Probablemente esté reemplazando a AUDIO_DEVICE_IN_BACK_MIC, pero esto está abierto para sugerencias.

Tengo dudas sobre cómo asegurarse de que Android utiliza este HAL para la entrada.

¿Necesito reemplazar audio.primary.default.so o debo dejarlo como audio.vcable.default.so?

Más específicamente: si no estoy reemplazando primaria, ¿cómo sabrá Android que usar mi HAL en lugar de primaria?


Actualizar:

Realmente podría usar cualquier ayuda en este trabajo. Cualquier puntero es útil.

He escrito un módulo Audio HAL. He añadido lo siguiente (elementos en negrita) a audio_policy.conf:

global:

global_configuration { attached_output_devices AUDIO_DEVICE_OUT_SPEAKER|**AUDIO_DEVICE_OUT_LINE** default_output_device AUDIO_DEVICE_OUT_SPEAKER attached_input_devices AUDIO_DEVICE_IN_BUILTIN_MIC|AUDIO_DEVICE_IN_BACK_MIC|AUDIO_DEVICE_IN_REMOTE_SUBMIX|**AUDIO_DEVICE_IN_LINE** } 

Y bajo audio_hw_modules

  vloop { inputs { vloop { sampling_rates 16000 channel_masks AUDIO_CHANNEL_IN_MONO formats AUDIO_FORMAT_PCM_16_BIT devices AUDIO_DEVICE_IN_LINE } } outputs { vloop { sampling_rates 16000 channel_masks AUDIO_CHANNEL_OUT_STEREO formats AUDIO_FORMAT_PCM_16_BIT devices AUDIO_DEVICE_OUT_LINE flags AUDIO_OUTPUT_FLAG_DIRECT } } } 

También agregué el siguiente (negrita) a AudioFlinger.cpp

 static const char * const audio_interfaces[] = { AUDIO_HARDWARE_MODULE_ID_PRIMARY, AUDIO_HARDWARE_MODULE_ID_A2DP, AUDIO_HARDWARE_MODULE_ID_USB, **AUDIO_HARDWARE_MODULE_ID_VLOOP** }; 

Puedo ver que durante el arranque, mi HAL se carga, y obtener estos registros:

 10-06 06:14:40.365 194-194/? I/AudioFlinger: Using default 3000 mSec as standby time. 10-06 06:14:46.664 194-194/? I/AudioPolicyService: AudioPolicyService CSTOR in new mode 10-06 06:14:46.673 194-194/? I/APM::ConfigParsingUtils: loadAudioPolicyConfig() loaded /system/etc/audio_policy.conf 10-06 06:14:46.681 194-194/? D/audio_hw_primary: adev_open: enter 10-06 06:14:46.797 194-194/? I/AudioFlinger: loadHwModule() Loaded primary audio interface from QCOM Audio HAL (audio) handle 1 10-06 06:14:46.797 194-194/? I/AudioFlinger: openOutput(), module 1 Device 2, SamplingRate 48000, Format 0x000001, Channels 3, flags 2 10-06 06:14:46.797 194-194/? I/AudioFlinger: AudioStreamOut::open(), mHalFormatIsLinearPcm = 1 10-06 06:14:46.798 194-194/? I/AudioFlinger: HAL output buffer size 240 frames, normal sink buffer size 960 frames 10-06 06:14:46.813 194-194/? I/AudioFlinger: Using module 1 has the primary audio interface 10-06 06:14:46.816 194-607/? I/AudioFlinger: AudioFlinger's thread 0xb4140000 ready to run 10-06 06:14:46.816 194-607/? D/audio_hw_primary: out_set_parameters: enter: usecase(1: low-latency-playback) kvpairs: routing=2 10-06 06:14:46.818 194-194/? I/AudioFlinger: openOutput(), module 1 Device 2, SamplingRate 48000, Format 0x000001, Channels 3, flags 8 10-06 06:14:46.818 194-194/? I/AudioFlinger: AudioStreamOut::open(), mHalFormatIsLinearPcm = 1 10-06 06:14:46.818 194-194/? I/AudioFlinger: HAL output buffer size 960 frames, normal sink buffer size 960 frames 10-06 06:14:46.818 194-608/? I/AudioFlinger: AudioFlinger's thread 0xb3dc0000 ready to run 10-06 06:14:46.818 194-607/? E/AudioFlinger: no wake lock to update! 10-06 06:14:46.818 194-608/? D/audio_hw_primary: out_set_parameters: enter: usecase(0: deep-buffer-playback) kvpairs: routing=2 10-06 06:14:46.818 194-608/? E/AudioFlinger: no wake lock to update! 10-06 06:14:46.820 194-609/? I/AudioFlinger: AudioFlinger's thread 0xb3c40000 ready to run 10-06 06:14:46.823 194-194/? I/AudioFlinger: loadHwModule() Loaded a2dp audio interface from A2DP Audio HW HAL (audio) handle 7 10-06 06:14:46.828 194-194/? I/AudioFlinger: loadHwModule() Loaded usb audio interface from USB audio HW HAL (audio) handle 8 10-06 06:14:46.832 194-194/? I/r_submix: adev_open(name=audio_hw_if) 10-06 06:14:46.832 194-194/? I/AudioFlinger: loadHwModule() Loaded r_submix audio interface from Wifi Display audio HAL (audio) handle 9 10-06 06:14:46.832 194-194/? D/r_submix: submix_audio_device_create_pipe_l(addr=0, idx=9) 10-06 06:14:46.833 194-610/? I/AudioFlinger: AudioFlinger's thread 0xb3bc0000 ready to run 10-06 06:14:46.833 194-194/? D/r_submix: submix_audio_device_release_pipe_l(idx=9) addr=0 10-06 06:14:46.833 194-194/? D/r_submix: submix_audio_device_destroy_pipe_l(): pipe destroyed 10-06 06:14:46.835 194-194/? D/audio_vloop: adev_open: audio_hw_if 10-06 06:14:46.835 194-194/? D/audio_vloop: adev_open(): 1678 10-06 06:14:46.835 194-194/? D/audio_vloop: adev_open(): 1685 10-06 06:14:46.835 194-194/? D/audio_vloop: adev_open(): 1688 10-06 06:14:46.835 194-194/? D/audio_vloop: adev_open(): 1722 10-06 06:14:46.835 194-194/? D/audio_vloop: adev_init_check(): 1252 10-06 06:14:46.835 194-194/? D/audio_vloop: adev_set_master_volume: 1.000000 10-06 06:14:46.835 194-194/? D/audio_vloop: adev_set_master_mute: 0 10-06 06:14:46.835 194-194/? I/AudioFlinger: loadHwModule() Loaded vloop audio interface from UI_audio_HW_HAL (audio) handle 11 10-06 06:14:46.835 194-194/? D/audio_vloop: adev_open_input_stream(): 1490 10-06 06:14:46.835 194-194/? D/audio_vloop: in_get_sample_rate(): 979 10-06 06:14:46.835 194-194/? D/audio_vloop: in_get_channels(): 1017 10-06 06:14:46.835 194-194/? D/audio_vloop: in_get_channels: 0x00000001 10-06 06:14:46.835 194-194/? D/audio_vloop: in_get_format(): 1029 10-06 06:14:46.836 194-194/? D/audio_vloop: in_get_format: 0x00000001 10-06 06:14:46.836 194-194/? D/audio_vloop: in_get_format(): 1029 10-06 06:14:46.836 194-194/? D/audio_vloop: in_get_format: 0x00000001 10-06 06:14:46.836 194-194/? D/audio_vloop: in_get_channels(): 1017 10-06 06:14:46.836 194-194/? D/audio_vloop: in_get_channels: 0x00000001 10-06 06:14:46.836 194-194/? D/audio_vloop: in_get_buffer_size(): 1005 10-06 06:14:46.836 194-194/? D/audio_vloop: in_get_buffer_size: 1600 10-06 06:14:46.836 194-194/? D/audio_vloop: in_get_buffer_size(): 1005 10-06 06:14:46.836 194-194/? D/audio_vloop: in_get_buffer_size: 1600 10-06 06:14:46.836 194-194/? D/audio_vloop: in_get_format(): 1029 10-06 06:14:46.836 194-194/? D/audio_vloop: in_get_format: 0x00000001 10-06 06:14:46.836 194-194/? D/audio_vloop: in_get_sample_rate(): 979 10-06 06:14:46.836 194-194/? D/audio_vloop: in_get_channels(): 1017 10-06 06:14:46.836 194-194/? D/audio_vloop: in_get_channels: 0x00000001 10-06 06:14:46.838 194-613/? I/AudioFlinger: AudioFlinger's thread 0xb3bc0000 ready to run 10-06 06:14:46.838 194-194/? D/audio_vloop: adev_close_input_stream(): 1570 10-06 06:14:46.839 194-194/? W/APM::AudioPolicyManager: Input device 00020000 unreachable 10-06 06:14:46.839 194-611/? D/audio_vloop: looper_thread(): 216: Entered 10-06 06:14:46.839 194-611/? D/audio_vloop: looper_thread(): 366: Exiting 10-06 06:15:07.137 616-616/? I/InputManager: Initializing input manager, mUseDevInputEventForAudioJack=false 10-06 06:15:10.155 616-616/? I/SystemServer: Audio Service 10-06 06:15:10.222 194-607/? E/AudioFlinger: no wake lock to update! 10-06 06:15:10.222 194-608/? E/AudioFlinger: no wake lock to update! 10-06 06:15:10.224 194-614/? D/audio_hw_primary: adev_set_mic_mute: state 0 10-06 06:15:10.224 194-614/? D/audio_vloop: adev_set_mic_mute: 0 10-06 06:15:14.061 194-614/? D/audio_hw_primary: adev_set_parameters: enter: A2dpSuspended=false 10-06 06:15:14.061 194-614/? D/audio_vloop: adev_set_parameters(): [A2dpSuspended=false] 10-06 06:15:14.084 194-194/? I/AudioFlinger: systemReady 10-06 06:15:16.308 194-194/? D/audio_hw_primary: adev_set_mic_mute: state 0 10-06 06:15:16.308 194-194/? D/audio_vloop: adev_set_mic_mute: 0 10-06 06:15:17.072 194-194/? D/audio_hw_primary: adev_set_parameters: enter: A2dpSuspended=false 10-06 06:15:17.072 194-194/? D/audio_vloop: adev_set_parameters(): [A2dpSuspended=false] 10-06 06:15:25.023 733-733/? W/AudioTrack: AUDIO_OUTPUT_FLAG_FAST denied by client; transfer 4, track 44100 Hz, output 48000 Hz 10-06 06:15:25.032 194-607/? D/audio_hw_primary: out_set_parameters: enter: usecase(1: low-latency-playback) kvpairs: routing=2 10-06 06:15:25.043 194-607/? D/audio_hw_primary: select_devices: out_snd_device(2: speaker) in_snd_device(0: none) 10-06 06:15:25.043 194-607/? D/audio_hw_primary: enable_snd_device: snd_device(2: speaker) 10-06 06:15:25.050 194-607/? D/audio_hw_primary: enable_audio_route: apply and update mixer path: low-latency-playback 10-06 06:15:26.431 1150-1298/? I/MicrophoneInputStream: mic_starting com.google.android.apps.gsa.speech.audio.ag@c6eb0e1 10-06 06:15:26.443 194-1585/? I/AudioFlinger: AudioFlinger's thread 0xb3bc0000 ready to run 10-06 06:15:26.447 1150-1298/? I/MicrophoneInputStream: mic_started com.google.android.apps.gsa.speech.audio.ag@c6eb0e1 10-06 06:15:26.457 194-1585/? D/audio_hw_primary: select_devices: out_snd_device(0: none) in_snd_device(38: voice-rec-mic) 10-06 06:15:26.457 194-1585/? D/audio_hw_primary: enable_snd_device: snd_device(38: voice-rec-mic) 10-06 06:15:26.460 194-1585/? D/audio_hw_primary: enable_audio_route: apply and update mixer path: audio-record 10-06 06:15:26.942 1150-1271/? I/AudioController: internalShutdown 10-06 06:15:26.943 1150-1271/? I/MicrophoneInputStream: mic_close com.google.android.apps.gsa.speech.audio.ag@c6eb0e1 10-06 06:15:26.943 1150-1298/? E/AudioRecord-JNI: Error -4 during AudioRecord native read 10-06 06:15:26.986 194-1585/? D/audio_hw_primary: disable_audio_route: reset and update mixer path: audio-record 10-06 06:15:26.987 194-1585/? D/audio_hw_primary: disable_snd_device: snd_device(38: voice-rec-mic) 10-06 06:15:27.066 194-607/? D/audio_hw_primary: out_set_parameters: enter: usecase(1: low-latency-playback) kvpairs: routing=2 10-06 06:15:27.100 194-607/? D/AudioFlinger: mixer(0xb4140000) throttle end: throttle time(7) 10-06 06:15:30.257 194-607/? D/audio_hw_primary: disable_audio_route: reset and update mixer path: low-latency-playback 10-06 06:15:30.257 194-607/? D/audio_hw_primary: disable_snd_device: snd_device(2: speaker) 10-06 06:15:30.262 194-607/? D/audio_hw_primary: out_set_parameters: enter: usecase(1: low-latency-playback) kvpairs: routing=2 10-06 06:15:30.272 194-607/? D/audio_hw_primary: select_devices: out_snd_device(2: speaker) in_snd_device(0: none) 10-06 06:15:30.273 194-607/? D/audio_hw_primary: enable_snd_device: snd_device(2: speaker) 10-06 06:15:30.280 194-607/? D/audio_hw_primary: enable_audio_route: apply and update mixer path: low-latency-playback 10-06 06:15:30.347 194-607/? D/AudioFlinger: mixer(0xb4140000) throttle end: throttle time(10) 10-06 06:15:31.517 194-607/? D/audio_hw_primary: out_set_parameters: enter: usecase(1: low-latency-playback) kvpairs: routing=2 10-06 06:15:31.751 1150-1298/? I/MicrophoneInputStream: mic_starting com.google.android.apps.gsa.speech.audio.ag@dd13203 10-06 06:15:31.762 194-1826/? I/AudioFlinger: AudioFlinger's thread 0xb3bc0000 ready to run 10-06 06:15:31.771 1150-1298/? I/MicrophoneInputStream: mic_started com.google.android.apps.gsa.speech.audio.ag@dd13203 10-06 06:15:31.780 194-1826/? D/audio_hw_primary: select_devices: out_snd_device(0: none) in_snd_device(38: voice-rec-mic) 10-06 06:15:31.780 194-1826/? D/audio_hw_primary: enable_snd_device: snd_device(38: voice-rec-mic) 10-06 06:15:31.783 194-1826/? D/audio_hw_primary: enable_audio_route: apply and update mixer path: audio-record 10-06 06:15:34.695 194-607/? D/audio_hw_primary: disable_audio_route: reset and update mixer path: low-latency-playback 10-06 06:15:34.695 194-607/? D/audio_hw_primary: disable_snd_device: snd_device(2: speaker) 10-06 06:15:34.850 1150-1271/? I/AudioController: internalShutdown 10-06 06:15:34.851 1150-1271/? I/MicrophoneInputStream: mic_close com.google.android.apps.gsa.speech.audio.ag@dd13203 10-06 06:15:34.851 1150-1298/? E/AudioRecord-JNI: Error -4 during AudioRecord native read 10-06 06:15:34.885 194-1826/? D/audio_hw_primary: disable_audio_route: reset and update mixer path: audio-record 10-06 06:15:34.885 194-1826/? D/audio_hw_primary: disable_snd_device: snd_device(38: voice-rec-mic) 

El mío es audio_vloop. Puedo ver que Android abre mi dispositivo, luego abre el flujo de entrada y luego cierra el flujo de entrada. Nunca intenta abrir el flujo de salida. Audio_vloop implementa los flujos de entrada y salida. Después de esto, Android nunca invoca nada en audio_vloop.

Hice una pequeña aplicación que reproduce audio (desde un archivo pcm por ahora). Quiero redirigir esta salida a mi HAL. Para lograr esto, creo que necesito hacer un AudioTrack.setPreferredDevice () en mi pista de audio. He encontrado que el Administrador de audio debe tener una lista de todos los dispositivos de audio.

Así que llamo

 AudioDeviceInfo aDevInfo[] = am.getDevices(AudioManager.GET_DEVICES_OUTPUTS); 

Sólo encuentra 1 dispositivo, más información en este dispositivo:

 10-06 06:37:01.962 3295-3663/? D/AudioPlayer: Have [1] devices 10-06 06:37:01.964 3295-3663/? D/AudioPlayer: devInfo[0]: [Landroid.media.AudioDeviceInfo;@90bd9da 10-06 06:37:01.965 3295-3663/? D/AudioPlayer: getProductName()AOSP on Flo 10-06 06:37:01.965 3295-3663/? D/AudioPlayer: getType()2 10-06 06:37:01.966 3295-3663/? D/AudioPlayer: isSink()true 10-06 06:37:01.966 3295-3663/? D/AudioPlayer: isSource()false 

Esto aparentemente es de audioPort que no he implementado. Así que no es de mi HAL.

Obviamente, he perdido uno o más pasos antes de que Android permita que mi aplicación hable con mi dispositivo.

Necesito poder enviar audio de mi aplicación a mi HAL. Más tarde, también necesito ser capaz de recibir audio de mi HAL (a través de AudioRecord etc).

¿Qué extrañé al integrar mi HAL en Android? ¿Necesito implementar puertos de audio? ¿Se requiere algo más?


Actualización 2

He encontrado que hay un error tipográfico en AOSP, en AudioPolicyManager.cpp@2922

En lugar de Output , imprime Input

Tenía este registro AudioPolicyManager: Input device 00020000 unreachable que no AudioPolicyManager: Input device 00020000 unreachable cuenta suponiendo que está hablando de dispositivo de entrada BT / A2DP.

Fijé el registro para mi dispositivo, y resulta ser el dispositivo de la Línea hacia fuera que queremos utilizar. Estoy depurando esta dirección ahora.

Respuestas encontradas.

Para salir:

  1. Las aplicaciones que no admiten AUDIO_CHANNEL_OUT_STEREO no están siendo abiertas por Android
  2. Las salidas que mencionan la bandera AUDIO_OUTPUT_FLAG_DIRECT no son abiertas automáticamente por Android. Esto es evidente en el código siguiente en AudioPolicyManager.cpp

      if ((outProfile->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) != 0) { continue; } 

    Desde aquí

Puede haber una manera de abrirlos en programatically, pero no he encontrado la respuesta a eso.

Estos dos, una vez fijos fueron suficientes para Android para empezar a utilizar mi salida.

Para en corriente:

En secuencia ya era una parte de los resultados de AudioManager.getDevices()

Así que fue posible leer de vloop en secuencia después de AudioTrack.setPreferredDevice() .

Para asegurarme de que otras aplicaciones lean la entrada de micrófono de vloop, tuve que declararla para implementar AUDIO_DEVICE_IN_BUILTIN_MIC . Para que esto funcione, también AUDIO_DEVICE_IN_BUILTIN_MIC de HAL primaria en audio_policy.conf .

Además, he hecho en estéreo de flujo sólo para mantener la compatibilidad con el formato de búfer de flujo de salida.

Después de estos cambios, veo que hay continuas llamadas de lectura y escritura que vienen a vloop.

ACTUALIZAR:

Posteriormente descubrí que el comportamiento mencionado anteriormente depende de la implementación del Administrador de Políticas de Audio. La mayoría de ellos se comportan de la misma manera (por ejemplo, la entrada más abierta de INBUILT_MIC para VOICE_RECOGNITION), pero algunos no pueden (Nexus Player) Para estos outliers, implemente lo que sus APM abran o modifique APM para abrir lo que implementa HAL.

  • Jugar dos sonidos Simutaneosly
  • Cancelación de ruido activo de Android
  • Archivo de audio inverso en Android
  • Valor de AudioSource para el micrófono USB en Android
  • Android grabación y reproducción + altavoz como una opción
  • TextToSpeech versión de compilación android no reproduce audio
  • Android (Java) Entrada de audio en tiempo real (micrófono y USB) y salida
  • El lazo de MediaPlayer de Android tiene brechas incluso con formato OGG
  • Cómo reproducir el archivo de audio Mp3 desde el servidor
  • Impedir mi aplicación de audio con NuPlayer en Android Lollipop 5.x?
  • Cómo convertir alto bitrate mp3 a una tasa más baja utilizando ffmpeg en android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.