Enrutamiento de audio

En Android 10, car_audio_configuration.xml reemplaza car_volumes_groups.xml y IAudioControl.getBusForContext . En el nuevo archivo de configuración, se define una lista de zonas. Cada zona tiene uno o más grupos de volúmenes con sus dispositivos asociados y cada dispositivo tiene los contextos que deben enrutarse dentro de esa zona. Es necesario que todos los contextos estén representados dentro de cada zona.

Configurar el enrutamiento de audio

Los archivos de política de audio, que normalmente se encuentran en la partición del proveedor, representan la configuración del hardware de audio de la placa. Todos los dispositivos a los que se hace referencia en car_audio_configuration.xml deben definirse dentro de audio_policy_configuration.xml .

Habilitar el enrutamiento AAOS

Para utilizar el enrutamiento basado en AAOS, debe establecer el indicador audioUseDynamicRouting en true :

<resources>
    <bool name="audioUseDynamicRouting">true</bool>
</resources>

Cuando es false , el enrutamiento y gran parte de CarAudioService se desactivarán y el sistema operativo volverá al comportamiento predeterminado de AudioService .

Zona primaria

De forma predeterminada, todo el audio se enrutará a la zona principal. Sólo puede haber una zona primaria, que se indica en la configuración con el atributo isPrimary="true" .

Configuración de muestra

Por ejemplo, un vehículo podría tener dos zonas: una zona principal y un sistema de entretenimiento en el asiento trasero. Con eso, un posible car_audio_configuration.xml se definiría de la siguiente manera:

<audioZoneConfiguration version="2.0">
       <zone name="primary zone" isPrimary="true">
           <volumeGroups>
               <group>
                   <device address="bus0_media_out">
                       <context context="music"/>
                       <context context="announcement"/>
                   </device>
                   <device address="bus3_call_ring_out">
                       <context context="call_ring"/>
                   </device>
                   <device address="bus6_notification_out">
                       <context context="notification"/>
                   </device>
                   <device address="bus7_system_sound_out">
                       <context context="system_sound"/>
                       <context context="emergency"/>
                       <context context="safety"/>
                       <context context="vehicle_status"/>
                   </device>
               </group>
               <group>
                   <device address="bus1_navigation_out">
                       <context context="navigation"/>
                   </device>
                   <device address="bus2_voice_command_out">
                       <context context="voice_command"/>
                   </device>
               </group>
               <group>
                   <device address="bus4_call_out">
                       <context context="call"/>
                   </device>
               </group>
               <group>
                   <device address="bus5_alarm_out">
                       <context context="alarm"/>
                   </device>
               </group>
           </volumeGroups>
       </zone>
        <zone name="rear seat zone" audioZoneId="1">
           <volumeGroups>
               <group>
                   <device address="bus100_rear_seat">
                       <context context="music"/>
                       <context context="navigation"/>
                       <context context="voice_command"/>
                       <context context="call_ring"/>
                       <context context="call"/>
                       <context context="alarm"/>
                       <context context="notification"/>
                       <context context="system_sound"/>
                       <context context="emergency"/>
                       <context context="safety"/>
                       <context context="vehicle_status"/>
                       <context context="announcement"/>
                   </device>
               </group>
           </volumeGroups>
    </zones>
</audioZoneConfiguration>

Aquí la zona primaria ha separado contextos para diferentes dispositivos. Esto permite que HAL aplique diferentes efectos de posprocesamiento y mezcla en la salida de cada dispositivo utilizando el hardware del vehículo. Los dispositivos se han organizado en cuatro grupos de volúmenes: medios, navegación, llamadas y alarmas. Si el sistema está configurado para useFixedVolume , los niveles de volumen de cada grupo se pasarán al HAL para aplicarlos a la salida de estos dispositivos.

Para la zona secundaria, la salida esperada es a través de un único dispositivo de salida. En este ejemplo, todos los usos se dirigen a un único dispositivo y grupo de volúmenes para simplificar las cosas.

Configuración de audio de la zona de ocupantes

En Android 11, car_audio_configuration.xml se amplió aún más para introducir dos campos nuevos, audioZoneId y occupantZoneId . El primero, audioZoneId se puede utilizar para controlar mejor la gestión de zonas. Por otro lado, occupantZoneId se puede utilizar para configurar el enrutamiento basado en ID de usuario.

Para utilizar estos nuevos campos, se requiere la versión 2 de car_audio_configuration.xml . Revisando la configuración de audio anterior pero utilizando el nuevo campo para la identificación de la zona de ocupante y la asignación de identificación de la zona de audio, la nueva configuración sin las definiciones del grupo de volúmenes se puede configurar como:

<audioZoneConfiguration version="2.0">
       <zone name="primary zone" isPrimary="true" occupantZoneId="0">
         ...
       </zone>
       <zone name="rear seat zone" audioZoneId="1" occupantZoneId="1">
         ...
       </zone>
    </zones>
</audioZoneConfiguration>

La configuración anterior define una asignación para la zona primaria a la zona de ocupantes 0 y audioZoneId 1 a occupantZoneId 1. En general, se puede configurar cualquier asignación entre la zona de ocupantes y la zona de audio, pero la asignación debe ser uno a uno. Estas son las reglas que definieron los dos nuevos campos:

  • El audioZoneId para la zona primaria siempre es cero
  • Los números audioZoneId y occupantZoneId no se pueden repetir
  • audioZoneId y occupantZoneId solo pueden tener una asignación uno a uno

Enrutamiento a través de un UID de aplicación

Se introdujo una serie de API ocultas en CarAudioManager en 10 para permitir que las aplicaciones consulten y establezcan zonas de audio y enfoque.

int[] getAudioZoneIds();
int getZoneIdForUid(int uid);
boolean setZoneIdForUid(int zoneId, int uid);
boolean clearZoneIdForUid(int uid);

Las API anteriores permitieron que una aplicación propia administrara el enrutamiento de audio según el UID de una aplicación. Como tal, también se necesitan tanto el ID de la zona de audio como el UID de la aplicación. Con esa información a mano, el enrutamiento de audio se puede configurar mediante la API CarAudioManager#setZoneIdForUid .

Cambiar zonas para una aplicación

De forma predeterminada, todo el audio se dirige a la zona principal. Para actualizar una aplicación para que se enrute a una zona diferente, use CarAudioManager#setZoneIdForUid :

// Find zone to play
int zoneId = ...

// Find application's uid
Int uid = mContext.getPackageManager()
        .getApplicationInfo(mContext.getPackageName(), 0)
        .uid;

if (mCarAudioManager.setZoneIdForUid(zoneId, info.uid)) {
    Log.d(TAG, "Zone successfully updated");
} else {
    Log.d(TAG, "Failed to change zone");
}

N Nota: Las transmisiones y el enfoque no pueden cambiar de zona dinámicamente. Por lo tanto, se debe detener la reproducción y volver a solicitar el enfoque para cambiar de zona.

Enrutamiento con ID de usuario

Si bien el enrutamiento basado en UID de una aplicación permite un control preciso del enrutamiento de audio de cada aplicación, también requiere que el enrutamiento de audio para cada aplicación se defina antes de que la aplicación realmente solicite el enfoque de audio y reproduzca audio. Para mitigar este problema y facilitar aún más que las aplicaciones de terceros reproduzcan audio sin modificaciones, CarAudioService utiliza la zona de ocupantes del automóvil y el mapeo de zonas de audio para definir la ruta basada en la identificación del usuario. De esta manera, cuando un usuario inicia sesión en la zona de ocupantes, se notifica al servicio de audio del automóvil. Con esta señal, la gestión del enfoque de audio y el enrutamiento se configuran automáticamente para todas las zonas de audio.

El enrutamiento de aplicaciones basado en UID aún se puede utilizar, pero debe realizarse independientemente del enrutamiento de ID de usuario. Esto significa que si se define la asignación de zona de ocupantes a zona de audio del automóvil, entonces el enrutamiento basado en UID está deshabilitado y al intentar llamar CarAudioManager#setZoneidForUid se producirá un error.

Si bien el enrutamiento de audio y la gestión de enfoque se han simplificado con la gestión de zonas de ocupantes, el usuario aún debe estar asignado a una zona de ocupantes. Esto se puede hacer utilizando CarOccupantZoneManager#assignProfileUserToOccupantZone . Esta API requiere permiso para administrar usuarios. La expectativa actual es que los OEM administren la asignación de zonas de usuario a ocupante a través de algún tipo de interfaz de usuario del sistema. Una vez hecho esto, el inicio de la aplicación, el enrutamiento de audio y la administración del enfoque se configurarán automáticamente para el usuario.

Enrutamiento con setPreferredDevice

Junto con los cambios anteriores, Android 11 también tiene una nueva API para consultar los dispositivos de salida asociados con cada zona, CarAudioManager#getOutputDeviceForUsage(int zoneId, int use).

La API se puede utilizar para consultar un dispositivo de salida para una zona particular y el uso de un atributo de audio. De esta manera, las aplicaciones propias pueden enrutar audio a diferentes zonas utilizando la API setPreferredDevice del reproductor. La API getOutputDeviceForUsage requiere PERMISSION_CAR_CONTROL_AUDIO_SETTINGS y es una API del sistema. A continuación se muestra un ejemplo de cómo encontrar el dispositivo multimedia para una zona particular y enrutarlo a ese dispositivo usando la API setPreferredDevice .

audioZoneId = ... ;
mediaDeviceInfo = mCarAudioManager
            .getOutputDeviceForUsage(audioZoneId, AudioAttributes.USAGE_MEDIA);
…
mPlayer.setPreferredDevice(mediaDeviceInfo);