Enfoque de audio

Antes de iniciar una transmisión lógica, una app debe solicitar el enfoque de audio con los mismos atributos de audio que se usan para su transmisión lógica. Si bien se recomienda enviar una solicitud de enfoque de este tipo, el sistema no la aplica. Algunas apps pueden omitir de forma explícita el envío de la solicitud para lograr comportamientos específicos (por ejemplo, para reproducir sonido de forma intencional durante una llamada telefónica).

Por este motivo, debes considerar el enfoque como una forma de controlar y resolver indirectamente la reproducción, y no como un mecanismo de control de audio principal. El vehículo no debe depender del sistema de enfoque para el funcionamiento del subsistema de audio.

Interacciones de enfoque

Para satisfacer las necesidades de AAOS, las solicitudes de enfoque de audio se controlan en función de interacciones predefinidas entre el CarAudioContext de la solicitud y el de los titulares de enfoque actuales. Existen tres tipos de interacciones: exclusivas, de rechazo y simultáneas.

Interacción exclusiva

En las interacciones exclusivas, solo una aplicación puede mantener el foco a la vez. Por lo tanto, la solicitud de enfoque entrante obtiene el enfoque mientras que el titular de enfoque existente pierde el enfoque. Un ejemplo de esto sería cuando un usuario inicia una nueva aplicación de música mientras ya se está reproduciendo música en una aplicación existente. Como ambas reproducen contenido multimedia, solo una de las aplicaciones puede mantener el foco a la vez. Como resultado, la solicitud de enfoque de la aplicación que se inició recientemente se muestra con AUDIOFOCUS_REQUEST_GRANTED y la aplicación que reproduce música recibe un evento de cambio de enfoque con un estado de pérdida que corresponde al tipo de solicitud que se realizó. Este es el modelo de interacción más común en Android.

Cómo rechazar una interacción

Con las interacciones de rechazo, la solicitud entrante siempre se rechaza. Intentar reproducir música mientras se está realizando una llamada es un ejemplo de una interacción rechazada. En este caso, si el selector de llamadas tiene el foco de audio para una llamada y una segunda aplicación solicita el foco para reproducir música, la aplicación de música recibe AUDIOFOCUS_REQUEST_FAILED en respuesta a su solicitud. Dado que se rechaza la solicitud de enfoque, no se envía ninguna pérdida de enfoque de ningún tipo al titular de enfoque actual.

Interacción simultánea

Las interacciones simultáneas son las más exclusivas de AAOS. Esto permite que las aplicaciones que soliciten el foco de audio en el vehículo puedan mantener el foco de forma simultánea con otras aplicaciones. Para que se produzca una interacción simultánea, se deben cumplir las siguientes condiciones. El:

Si se cumplen estos criterios, la solicitud de enfoque se muestra con AUDIOFOCUS_REQUEST_GRANTED, mientras que el titular de enfoque actual no tiene cambios en el enfoque. Sin embargo, si el titular de enfoque actual opta por recibir eventos de ocultación o detenerse cuando se oculta, el titular de enfoque actual pierde el enfoque al igual que con una interacción exclusiva.

Cómo controlar transmisiones simultáneas

Si bien la interacción simultánea tiene muchas aplicaciones útiles, los OEMs deben encargarse de la combinación y la atenuación a nivel del hardware en todos los dispositivos de salida. Por este motivo, se recomienda que los CarAudioContext solo se enruten al mismo dispositivo de salida que los CarAudioContext con los que no se pueden reproducir de forma simultánea. Si tienes dispositivos de salida separados para transmisiones simultáneas, el sistema HAL puede omitir una de las transmisiones antes de mezclarlas o enrutar las transmisiones físicas a diferentes bocinas en el vehículo. Si las transmisiones lógicas se mezclan en Android, sus ganancias no se alteran y se entregan como parte de la misma transmisión física.

Por ejemplo, cuando la navegación y el contenido multimedia se entregan de forma simultánea, la ganancia del flujo de contenido multimedia se puede reducir temporalmente (silenciar) para que se puedan escuchar con mayor claridad las instrucciones de navegación. Como alternativa, la transmisión de navegación se puede enrutar a las bocinas del lado del conductor mientras el contenido multimedia continúa reproduciéndose en el resto de la cabina.

Matriz de interacción

En la siguiente tabla, se muestra la matriz de interacción como la define CarAudioService. Las filas representan el CarAudioContext del contenedor de enfoque actual y las columnas representan el de la solicitud entrante.

En un ejemplo, en el que una app de música multimedia tiene el enfoque y una app de navegación solicita el enfoque, la matriz muestra que las dos interacciones pueden reproducirse de forma simultánea, siempre que se cumplan los otros criterios de Interacciones simultáneas.

Debido a las interacciones simultáneas, es posible que exista más de un elemento de enfoque. En este caso, una solicitud de enfoque entrante se compara con cada uno de los titulares de enfoque actuales antes de decidir qué tipo de interacción aplicar. En este caso, gana la interacción más conservadora (rechazo, luego exclusiva y, por último, simultánea).

En la siguiente tabla, se proporcionan las interacciones de enfoque entre CarAudioContext para una solicitud de enfoque entrante (columnas) y el contexto de los titulares de enfoque existentes (filas). Cada celda representa el tipo de interacción esperado para los dos contextos.

Interacciones de foco de audio

Figura 1: Interacciones de foco de audio

En Android 11, se introdujo un nuevo parámetro de configuración del usuario para permitir que los usuarios alteren el comportamiento de interacción entre la navegación y las llamadas telefónicas. Cuando se establece, android.car.KEY_AUDIO_FOCUS_NAVIGATION_REJECTED_DURING_CALL cambia la interacción entre las solicitudes de enfoque NAVIGATION entrantes y los titulares de enfoque CALL actuales de simultánea a rechazo. Por lo tanto, si un usuario prefiere que no se interrumpa su llamada con instrucciones de navegación, puede habilitar este parámetro de configuración. Este valor se conserva para el usuario y se puede establecer de forma dinámica para que las solicitudes de enfoque posteriores respeten el nuevo valor de configuración.

Foco de audio demorable

En Android 11, AAOS agregó compatibilidad para solicitar enfoque de audio diferido. Esto permite que se retrasen las solicitudes de enfoque no transitorias cuando su interacción con los titulares de enfoque actuales normalmente provocaría que se rechacen. Una vez que un cambio de enfoque genera un estado en el que la solicitud diferida puede enfocarse, se otorga la solicitud.

Reglas para solicitudes de enfoque de audio retrasadas

  • Solo solicitudes no transitorias: Como se mencionó anteriormente, solo se puede realizar una solicitud retrasada para fuentes no transitorias. Esto se hace para evitar que se reproduzca un sonido transitorio mucho después de que sea relevante.
  • Solo se puede retrasar una solicitud a la vez: Si se realiza una solicitud que se puede retrasar mientras ya hay una solicitud retrasada, la solicitud retrasada original recibe un evento de cambio AUDIOFOCUS_LOSS y la solicitud nueva recibe una respuesta síncrona de AUDIOFOCUS_REQUEST_DELAYED.
  • Las solicitudes demorables deben tener un OnAudioFocusChangeListener. Una vez que se retrasa una solicitud, el objeto de escucha se usa para notificar al solicitante cuando se otorga (AUDIOFOCUS_GAIN) o se rechaza más adelante (AUDIOFOCUS_LOSS).

Solicita foco demorable

Para compilar una solicitud que se puede retrasar, usa AudioFocusRequest.Builder#setAcceptsDelayedFocusGain:

mMediaWithDelayedFocusListener = new MediaWithDelayedFocusListener();

mDelayedFocusRequest = new AudioFocusRequest
     .Builder(AudioManager.AUDIOFOCUS_GAIN)
     .setAudioAttributes(mMusicAudioAttrib)
     .setOnAudioFocusChangeListener(mMediaWithDelayedFocusListener)
     .setForceDucking(false)
     .setWillPauseWhenDucked(false)
     .setAcceptsDelayedFocusGain(true)
     .build();

Luego, cuando realices la solicitud, controla la respuesta AUDIOFOCUS_REQUEST_DELAYED:

int delayedFocusRequestResults = mAudioManager.requestAudioFocus(mDelayedFocusRequest);
if (delayedFocusRequestResults == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
// start audio playback
return;
}
if (delayedFocusRequestResults == AudioManager.AUDIOFOCUS_REQUEST_DELAYED) {
     // audio playback delayed to audio focus listener
     return;
}

Cuando se retrasa la solicitud, el objeto de escucha de enfoque es responsable de controlar los cambios de enfoque:

private final class MediaWithDelayedFocusListener implements
OnAudioFocusChangeListener {
       @Override
       public void onAudioFocusChange(int focusChange) {
           synchronized (mLock) {
               switch (focusChange) {
                   case AudioManager.AUDIOFOCUS_GAIN:
                        // Start focus playback
                   case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
                        // Pause media transiently
                   case AudioManager.AUDIOFOCUS_LOSS:
                        // Stop media

Administración de enfoque de varias zonas

En el caso de los vehículos con varias zonas de audio, el enfoque de audio se administra de forma independiente para cada zona. Por lo tanto, una solicitud a una zona no tiene en cuenta lo que mantiene el enfoque en otras zonas ni hace que los elementos que tienen el enfoque en otras zonas pierdan el enfoque. Con esto, el enfoque de la cabina principal se puede administrar por separado de un sistema de entretenimiento para asientos traseros, lo que evita interrumpir la reproducción de audio en una zona debido a los cambios de enfoque en otra.

Para todas las aplicaciones, CarAudioService se encarga de la administración de enfoque de forma automática. La zona de audio de una solicitud de enfoque se determina según su UserId o UID asociado. Para obtener más información, consulta Enrutamiento de audio.

Cómo solicitar audio de varias zonas de forma simultánea

Si una app quiere reproducir audio en varias zonas de forma simultánea, debe solicitar el enfoque para cada zona. Para ello, incluye AUDIOFOCUS_EXTRA_REQUEST_ZONE_ID en el paquete:

// Create attribute with bundle and AUDIOFOCUS_EXTRA_REQUEST_ZONE_ID
Bundle bundle = new Bundle();
bundle.putInt(CarAudioManager.AUDIOFOCUS_EXTRA_REQUEST_ZONE_ID,
               zoneId);

AudioAttributes attributesWithZone = new AudioAttributes.Builder()
     .setUsage(AudioAttributes.USAGE_MEDIA)
     .addBundle(bundle)
     .build();

// Create focus request using built attributesWithZone

Este parámetro del paquete permite que el solicitante anule las asignaciones automáticas de zonas de audio para usar el ID de zona especificado. Por lo tanto, con esto, una app podría emitir solicitudes independientes para diferentes zonas de audio.

Foco de audio de HAL

A partir de Android 11, el HAL ahora está habilitado para solicitar el enfoque en nombre de transmisiones externas. Si bien son opcionales, se recomienda usar estas APIs para permitir que los sonidos externos sean mejores participantes en el ecosistema de Android y para proporcionar una experiencia del usuario más fluida.

Ten en cuenta que el HAL sigue siendo responsable de realizar la llamada final sobre qué sonidos deben tener prioridad. En este sentido, los sonidos de emergencia y seguridad críticos deben reproducirse independientemente de si se le otorga o no enfoque de audio al HAL, y deben seguir reproduciéndose según corresponda, incluso si el HAL pierde el enfoque de audio. Lo mismo sucede con cualquier sonido que exijan las reglamentaciones.

Del mismo modo, el HAL debe silenciar de forma proactiva las transmisiones de Android según corresponda cuando se reproducen sonidos de emergencia o de seguridad críticos para garantizar que se escuchen con claridad.

AudioControl@2.0

La versión 2.0 de la HAL de AudioControl presenta varias APIs nuevas:

API Propósito
IAudioControl#registerFocusListener Registra una instancia de IFocusListener con el HAL de AudioControl. Este objeto de escucha permite que el HAL solicite y abandone el foco de audio. Se espera que el HAl proporcione una instancia de ICloseHandle que Android usará para cancelar el registro del objeto de escucha.
IAudioControl#onAudioFocusChange Notifica al HAL los cambios de estado para enfocar las solicitudes que realiza el HAL a través de IFocusListener. Esto incluye las respuestas a las solicitudes de enfoque inicial.
IFocusListener#requestAudioFocus Las solicitudes se enfocan en nombre del HAL para un uso, un ID de zona y un tipo de ganancia de enfoque especificados.
IFocusListener#abandonAudioFocus Abandona las solicitudes de enfoque de HAL existentes para el uso y el ID de zona especificados.

El HAL puede tener varias solicitudes de enfoque al mismo tiempo, pero se limita a una solicitud por uso y vinculación de ID de zona. Ten en cuenta que Android supone que el HAL comienza a reproducir sonidos para un uso de inmediato una vez que se realiza una solicitud y continúa haciéndolo hasta que abandona el enfoque.

Además de registerFocusListener, todas estas solicitudes son oneway para garantizar que Android no retrase el HAL mientras se procesa una solicitud de enfoque. El HAL no debe esperar a obtener el enfoque antes de reproducir sonidos esenciales para la seguridad. Es opcional que el sistema HAL detecte y responda a los cambios en el enfoque de audio a través de IAudioControl#onAudioFocusChange, aunque se recomienda cuando corresponda.