Cómo compartir entradas de audio

Por lo general, la entrada de audio proviene del micrófono integrado, un micrófono externo o una interfaz de audio conectada al dispositivo. La entrada de audio también puede provenir de una conversación telefónica.

A veces, dos o más apps pueden querer "capturar" la misma entrada de audio. Es posible que realicen diferentes tareas. Por ejemplo, algunas apps que reciben audio pueden estar "grabando", como una grabadora de voz simple, mientras que otras apps pueden estar "escuchando", como el Asistente de Google o un servicio de accesibilidad que responde a comandos de voz.

En cualquier caso, estas apps quieren recibir entrada de audio. En esta página, usamos el término "capturar" independientemente de si una app está grabando o solo escuchando.

Si dos o más apps quieren capturar audio al mismo tiempo, puede haber un problema para entregar la señal de audio de la misma fuente a todas ellas. En esta página, se describe cómo el sistema Android comparte la entrada de audio entre varias apps que capturan audio.

Comportamiento anterior a Android 10

Antes de Android 10, la transmisión de audio de entrada solo podía capturarse con una app a la vez. Si alguna app ya estaba grabando o escuchando audio, tu app podía crear un AudioRecord objeto, pero se mostraría un error cuando llamaras a AudioRecord.startRecording() y no se iniciaría la grabación.

Una excepción a esta regla era cuando una app con privilegios (como el Asistente de Google o un servicio de accesibilidad) tenía el permiso android.permission.CAPTURE_AUDIO_HOTWORD y usaba una fuente de audio de tipo HOTWORD. En este caso, otra app podía comenzar a grabar. Cuando eso sucedía, la app con privilegios finalizaba y la app nueva capturaba la entrada.

Se agregó un cambio más en Android 9: solo las apps que se ejecutan en primer plano (o un servicio en primer plano) podían capturar la entrada de audio. Cuando una app sin un servicio en primer plano o un componente de IU en primer plano comenzaba a capturar, la app seguía ejecutándose, pero recibía silencio, incluso si era la única app que capturaba audio en ese momento.

Comportamiento de Android 10

El comportamiento anterior a Android 10 es "el primero en llegar es el primero en ser atendido". Una vez que una app comienza a capturar audio, ninguna otra app puede acceder a la entrada de audio hasta que se detenga la app que está capturando audio.

Android 10 impone un esquema de prioridad que puede cambiar la transmisión de audio de entrada entre las apps mientras se ejecutan. En la mayoría de los casos, si una app nueva adquiere la entrada de audio, la app que capturaba anteriormente sigue ejecutándose, pero recibe silencio. En algunos casos, el sistema puede seguir entregando audio a ambas apps. A continuación, se explican las diferentes situaciones de uso compartido.

Este esquema es similar a la forma en que el foco de audio controla varias apps que compiten por el uso de la salida de audio. Sin embargo, el foco de audio se administra mediante solicitudes programáticas para obtener y liberar el foco, mientras que el esquema de cambio de entrada que se describe aquí se basa en una política de priorización que se aplica automáticamente cada vez que una app nueva comienza a capturar audio.

Para capturar audio, Android distingue dos tipos de apps:

  • El usuario instala las apps "ordinarias".
  • Las apps "con privilegios" vienen preinstaladas en el dispositivo. Estas incluyen el Asistente de Google y todos los servicios de accesibilidad.

Además, una app se trata de manera diferente si usa una fuente de audio "sensible a la privacidad" : CAMCORDER o VOICE_COMMUNICATION.

Las reglas de priorización para usar y compartir la entrada de audio son las siguientes:

  • Las apps con privilegios tienen mayor prioridad que las apps ordinarias.
  • Las apps con UIs visibles en primer plano tienen mayor prioridad que las apps en segundo plano.
  • Las apps que capturan audio de una fuente sensible a la privacidad tienen mayor prioridad que las que no lo hacen.
  • Dos apps ordinarias nunca pueden capturar audio al mismo tiempo.
  • En algunas situaciones, una app con privilegios puede compartir la entrada de audio con otra app.
  • Si dos apps en segundo plano de la misma prioridad capturan audio, la última que se inició tiene mayor prioridad.

Situaciones de uso compartido

Cuando dos apps intentan capturar audio, es posible que ambas puedan recibir la señal de entrada o que una de ellas reciba silencio.

Hay cuatro situaciones principales:

  • Asistente + app ordinaria
  • Servicio de accesibilidad + app ordinaria
  • Dos apps ordinarias
  • Llamada de voz + app ordinaria

Asistente + app ordinaria

El Asistente es una app con privilegios porque está preinstalada y tiene la función RoleManager.ROLE_ASSISTANT. Cualquier otra app preinstalada con esta función se trata de manera similar.

Android comparte el audio de entrada según estas reglas:

  • El Asistente puede recibir audio (sin importar si está en primer plano o en segundo plano), a menos que otra app que use una fuente de audio sensible a la privacidad ya esté capturando.

  • La app recibe audio, a menos que el Asistente tenga un componente de IU visible en la parte superior de la pantalla.

Ten en cuenta que ambas apps reciben audio solo cuando el Asistente está en segundo plano y la otra app no captura desde una fuente de audio sensible a la privacidad.

Servicio de accesibilidad + app ordinaria

Un AccessibilityService requiere una estricta declaración.

Android comparte el audio de entrada según estas reglas:

  • Si la IU del servicio está en la parte superior, tanto el servicio como la app reciben entrada de audio. Este comportamiento ofrece funciones como controlar una llamada de voz o una captura de video con comandos de voz.

  • Si el servicio no está en la parte superior, este caso se trata como el caso ordinario de dos apps que se muestra a continuación.

Dos apps ordinarias

Cuando dos apps capturan de manera simultánea, solo una recibe audio y la otra recibe silencio.

Android comparte el audio de entrada según estas reglas:

  • Si ninguna de las apps es sensible a la privacidad, la app con una IU en la parte superior recibe audio. Si ninguna de las apps tiene una IU, la que comenzó a capturar más recientemente recibe audio.
  • Si una de las apps es sensible a la privacidad, recibe audio y la otra app recibe silencio, incluso si tiene una IU en la parte superior o comenzó a capturar más recientemente.
  • Si ambas apps son sensibles a la privacidad, la app que comenzó a capturar más recientemente recibe audio y la otra recibe silencio.

Llamada de voz + app ordinaria

Una llamada de voz está activa si el modo de audio que muestra AudioManager.getMode() es MODE_IN_CALL o MODE_IN_COMMUNICATION.

Android comparte el audio de entrada según estas reglas:

Comportamiento de Android 11

Android 11 (nivel de API 30) observa el esquema de prioridad de Android 10 que se describió anteriormente. También proporciona métodos nuevos en AudioRecord, MediaRecorder y AAudioStream que habilitan y deshabilitan la capacidad de capturar audio de manera simultánea, independientemente del caso de uso seleccionado.

Los nuevos métodos son los siguientes:

Cuando se establece setPrivacySensitive() como true, el caso práctico de captura es privado y ni siquiera un asistente con privilegios puede realizar capturas simultáneas. Este parámetro de configuración anula el comportamiento predeterminado que depende de la fuente de audio. Por ejemplo, VOICE_COMMUNICATION es privado de forma predeterminada, pero UNPROCESSED no lo es.

Cambios de configuración

Cuando varias apps capturan audio de manera simultánea, solo una o dos de ellas están "activas" (reciben audio); las demás están silenciadas (reciben silencio). Cuando cambian las apps activas, el framework de audio puede volver a configurar las rutas de audio según estas reglas:

  • El dispositivo de entrada de audio para cada app activa puede cambiar (por ejemplo, del micrófono integrado a unos auriculares Bluetooth conectados).
  • Se habilita el procesamiento previo asociado con la app activa de mayor prioridad. Se ignora todo el procesamiento previo.

Dado que una app activa puede silenciarse cuando se activa una app de mayor prioridad, puedes registrar un AudioManager.AudioRecordingCallback en el AudioRecord o MediaRecorder objeto para recibir una notificación cuando cambie la configuración. Los posibles cambios podrían ser los siguientes:

  • Captura silenciada o no silenciada
  • Dispositivo cambiado
  • Procesamiento previo cambiado
  • Propiedades de la transmisión cambiadas (tasa de muestreo, máscara de canal, formato de muestra)

Debes llamar a AudioRecord.registerAudioRecordingCallback() antes de que se inicie la captura. La devolución de llamada se ejecuta solo cuando la app recibe audio y se produce un cambio.

El método onRecordingConfigChanged() muestra un AudioRecordingConfiguration que contiene el estado actual de la captura de audio. Usa los siguientes métodos para obtener información sobre el cambio:

isClientSilenced()
Muestra verdadero si el audio que se muestra al cliente se silencia actualmente debido a la política de captura.
getAudioDevice()
Muestra el dispositivo de audio activo.
getEffects()
Muestra el efecto de procesamiento previo activo. Ten en cuenta que el efecto activo podría no ser el mismo que el que muestra getClientEffects() si el cliente no es la app activa de mayor prioridad.
getFormat()
Muestra las propiedades de la transmisión. Ten en cuenta que los datos de audio reales que recibe el cliente siempre respetan el formato requerido que muestra getClientFormat(). El framework realiza automáticamente el remuestreo, el canal y la conversión de formato necesarios desde el formato que se usa en la interfaz de hardware hasta el formato especificado por el cliente.
AudioRecord.getActiveRecordingConfiguration()
Muestra la configuración de grabación activa.

Puedes obtener una vista general de todas las grabaciones activas en el dispositivo llamando a AudioManager.getActiveRecordingConfigurations().