Contrôle audio HAL

Le contrôle audio HAL a été introduit dans Android 9 pour prendre en charge les cas d'utilisation audio pertinents pour l'automobile. Depuis Android 14, le contrôle audio HAL prend en charge :

  • Fondu et équilibre
  • Demande de focus audio HAL
  • Mise en sourdine et esquivement de l'appareil
  • Modifications du gain du périphérique audio
  • Modifications de la configuration du port audio

La figure 1 montre un aperçu de haut niveau de l'architecture du service audio de voiture, dans laquelle le service audio de voiture communique avec le HAL de commande audio.

Configurer l'audio multizone

Figure 1. Configurez l'audio multizone.

Fondu et balance audio

Contrôle audio HIDL La version 1 de HAL a été introduite dans Android 9 pour prendre en charge le fondu et l'équilibre audio dans les cas d'utilisation automobile. Séparé des effets audio génériques déjà fournis dans Android, ce mécanisme permet aux applications système de définir la balance audio et le fondu via les API CarAudioManager :

class CarAudioManager {
       /**
       *   Adjust the relative volume in the front vs back of the vehicle cabin.
       *
       *   @param value in the range -1.0 to 1.0 for fully toward the back through
       *   fully toward the front. 0.0 means evenly balanced.
       */
       @SystemApi
       @RequiresPermission(Car.PERMISSION_CAR_CONTROL_AUDIO_VOLUME)
       public void setFadeTowardFront(float value);

       /**
       *   Adjust the relative volume on the left vs right side of the vehicle cabin.
       *
       *   @param value in the range -1.0 to 1.0 for fully toward the left through
       *   fully toward the right. 0.0 means evenly balanced.
       */
       @SystemApi
       @RequiresPermission(Car.PERMISSION_CAR_CONTROL_AUDIO_VOLUME)
       public void setBalanceTowardRight(float value);
}

Une fois ces API appelées, les API HAL de contrôle audio respectives sont appelées depuis le service audio de la voiture :

interface IAudioControl {
       /**
       *   Control the right/left balance setting of the car speakers.
       */
       oneway setBalanceTowardRight(float value);

       /**
       *   Control the fore/aft fade setting of the car speakers.
       */
       oneway setFadeTowardFront(float value);
}

L'API est disponible sur toutes les versions du contrôle audio HAL, y compris la nouvelle interface AIDL HAL.

Demande de focus audio de HAL

AAOS, similaire à Android, s'appuie sur la participation active d'applications axées sur l'audio pour gérer la lecture audio dans les voitures. Les informations de focus sont utilisées pour gérer les flux à contrôler pour le volume et l'atténuation. Ainsi, pour développer davantage l'accent audio et fournir une meilleure intégration des sons spécifiques à la voiture dans l'expérience Android, les attributs audio suivants ont été introduits dans Android 11 :

  • EMERGENCY
  • SAFETY
  • VEHICLE_STATUS
  • ANNOUNCEMENT

En plus de ce changement, un mécanisme a été ajouté pour permettre aux sons provenant de l'extérieur d'Android de participer aux demandes de focus audio. Ainsi, le contrôle audio HIDL HAL version 2 a été introduit pour permettre les demandes de focus provenant de l'extérieur d'Android :

interface IAudioControl {
       /**
       *   Registers focus listener to be used by HAL for requesting and
       *   abandoning audio focus.
       *   @param listener the listener interface
       *   @return closeHandle A handle to unregister observer.
       */
       registerFocusListener(IFocusListener listener)
       generates (ICloseHandle closeHandle);

       /**
       *   Notifies HAL of changes in audio focus status for focuses requested
       *   or abandoned by the HAL.
       *
       *   @param usage The audio usage associated with the focus change
       *   @param zoneId The identifier for the audio zone that the HAL is
       *   playing the stream in
       *   @param focusChange the AudioFocusChange that has occurred
       */
       oneway onAudioFocusChange(bitfield<AudioUsage> usage, int32_t zoneId,
       bitfield<AudioFocusChange> focusChange);
}

IFocusListener est défini comme :

interface IFocusListener {
       /**
       *   Called whenever HAL is requesting focus as it is starting to play
       *   audio of a given usage in a specified zone.
       *
       *   @param usage The audio usage associated with the focus request
       *    {@code AttributeUsage}
       *   @param zoneId The identifier for the audio zone where the HAL is
       *    requesting focus
       *   @param focusGain The AudioFocusChange associated with this request.
       */
       oneway requestAudioFocus(bitfield<AudioUsage> usage,
       int32_t zoneId, bitfield<AudioFocusChange> focusGain);
       /**
       *   Called whenever HAL is abandoning focus as it is finished playing audio
       *   of a given usage in a specific zone.
       *
       *   @param usage The audio usage for which the HAL is abandoning focus
       *    {@code AttributeUsage}
       *   @param zoneId The identifier for the audio zone that the HAL
       *    abandoning focus
       */
       oneway abandonAudioFocus(bitfield<AudioUsage> usage, int32_t zoneId);
}

Les API ci-dessus peuvent être utilisées respectivement pour demander et abandonner le focus audio du HAL. En réponse, le service audio de la voiture considère la demande de focus audio et transmet les résultats de manière asynchrone à la méthode IAudioControl#onAudioFocusChange .

Cette API peut également être utilisée pour surveiller les modifications de la demande de focus audio provenant du HAL de contrôle audio. En général, toute demande de focus audio permanente provenant de HAL est considérée comme active , ce qui diffère d'une demande de focus audio d'Android, dans laquelle seule la lecture d'une piste audio active correspondante est considérée comme active.

Migrer HIDL vers AIDL contrôle audio HAL

Avec l'avènement de l'AIDL et la migration requise dans Android 12 (pour en savoir plus, voir AIDL pour les HAL ), le contrôle audio HAL a été migré vers AIDL. Pour les API de contrôle audio HIDL version 2 existantes, la migration a nécessité des mises à jour mineures des méthodes existantes :

interface IAudioControl {
       /**
       *   Notifies HAL of changes in audio focus status for focuses requested
       *   or abandoned by the HAL.
       *
       *   @param usage The audio usage associated with the focus change
       *        {@code AttributeUsage}. See {@code audioUsage} in
       *        audio_policy_configuration.xsd for the list of allowed values.
       *   @param zoneId The identifier for the audio zone that the HAL is
       *        playing the stream in
       *   @param focusChange the AudioFocusChange that has occurred.
       */
       oneway void onAudioFocusChange(in String usage, in int zoneId,
              in AudioFocusChange focusChange);
       /**
       *   Registers focus listener to be used by HAL for requesting and
       *   abandoning audio focus.
       *   @param listener the listener interface.
       */
       oneway void registerFocusListener(in IFocusListener listener);
       /**
       *   Control the right/left balance setting of the car speakers.
       */
       oneway void setBalanceTowardRight(in float value);
       /**
       *   Control the fore/aft fade setting of the car speakers.
       */
       oneway void setFadeTowardFront(in float value);
}

Et le IFocusListener correspondant :

       interface IFocusListener {
       /**
       *   Called whenever HAL is abandoning focus as it is finished playing audio
       *   of a given usage in a specific zone.
       *
       *   @param usage The audio usage for which the HAL is abandoning focus
       *        {@code AttributeUsage}. See {@code audioUsage} in
       *        audio_policy_configuration.xsd for the list of allowed values.
       *   @param zoneId The identifier for the audio zone that the HAL
       *        abandoning focus
       */
       oneway void abandonAudioFocus(in String usage, in int zoneId);
       /**
       *   Called whenever HAL is requesting focus as it is starting to play audio
       *        of a given usage in a specified zone.
       *
       *   @param usage The audio usage associated with the focus request
       *        {@code AttributeUsage}. See {@code audioUsage} in
       *        audio_policy_configuration.xsd for the list of allowed values.
       *   @param zoneId The identifier for the audio zone where the HAL is
       *        requesting focus
       *   @param focusGain The AudioFocusChange associated with this request.
       */
       oneway void requestAudioFocus(in String usage, in int zoneId,
              in AudioFocusChange focusGain);
}

Mise en sourdine du groupe de volume

Android 12 a introduit la mise en sourdine des groupes de volume pour permettre un contrôle plus complet de la sourdine lors des interactions audio de l'utilisateur. Cela permet au contrôle audio HAL de recevoir les événements de mise en sourdine interceptés par le service audio de la voiture.

Pour activer la fonctionnalité, les constructeurs OEM doivent définir la configuration audioUseCarVolumeGroupMuting sur true dans le config.xml du service de voiture :

<!-- Configuration to enable muting of individual volume groups.
If this is set to false, muting of individual volume groups is disabled,
instead muting will toggle master mute. If this is set to true, car volume
group muting is enabled and each individual volume group can be muted separately. -->
<bool name="audioUseCarVolumeGroupMuting">true</bool>

Avant Android 13, la configuration devait être remplacée par une superposition de ressources d'exécution pour packages/services/Car/service/res/values/config.xml (pour en savoir plus, voir Personnalisation de la construction avec des superpositions de ressources ). À partir d'Android 13, vous pouvez utiliser les superpositions de ressources d'exécution pour modifier une valeur de configuration. Pour en savoir plus, consultez Modifier la valeur des ressources d'une application au moment de l'exécution .

Les applications système peuvent déterminer si la fonctionnalité est activée à l'aide de l'API CarAudioManager#isAudioFeatureEnabled . Le paramètre transmis doit être la constante CarAudioManager.AUDIO_FEATURE_VOLUME_GROUP_MUTING . La méthode renvoie true si la fonctionnalité est activée sur l'appareil, sinon false .

En plus d'activer la fonctionnalité audioUseCarVolumeGroupMuting , le contrôle audio AIDL HAL doit implémenter le mécanisme de mise en sourdine du groupe de volume :

interface IAudioControl {
       /**
       *   Notifies HAL of changes in output devices that the HAL should apply
       *   muting to.
       *
       *   This will be called in response to changes in audio mute state for each
       *   volume group and will include a {@link MutingInfo} object per audio
       *   zone that experienced a mute state event.
       *
       *   @param mutingInfos an array of {@link MutingInfo} objects for the audio
       *   zones where audio mute state has changed.
       */
       oneway void onDevicesToMuteChange(in MutingInfo[] mutingInfos);
}

Lorsque les informations de mise en sourdine contiennent les informations de mise en sourdine pertinentes pour le système audio :

parcelable MutingInfo {
       /**
       *   ID of the associated audio zone
       */
       int zoneId;
       /**
       *   List of addresses for audio output devices that should be muted.
       */
       String[] deviceAddressesToMute;
       /**
       *   List of addresses for audio output devices that were previously be
       *   muted and should now be unmuted.
       */
       String[] deviceAddressesToUnmute;
}

AAOS dispose de deux mécanismes différents de mise en sourdine, basés sur :

  • Événements clés utilisant l'audio KEYCODE_VOLUME_MUTE {:.external}.

  • Appels directs vers le service audio de la voiture à l'aide de l'API de sourdine du gestionnaire audio de la voiture, CarAudioManager#setVolumeGroupMute .

Lorsqu'ils sont activés, les deux mécanismes déclenchent une sourdine d'appel vers le HAL de contrôle audio.

Ducking audio de voiture

Android 12 a introduit le ducking audio de voiture pour optimiser le contrôle de la lecture simultanée des flux audio. Cela permet aux constructeurs OEM de mettre en œuvre leur propre comportement d'esquive en fonction de la configuration audio physique d'une voiture et de l'état de lecture actuel, tels que déterminés par le service audio de la voiture.

Le mécanisme d'esquive est basé sur les changements de la pile de focus audio. Chaque fois qu'un changement de focus se produit (qu'il s'agisse d'une demande de focus ou d'un abandon de focus), le contrôle audio HAL en est informé. Semblable à la prise en charge de la mise en sourdine du groupe de volume de la voiture, l'atténuation audio de la voiture peut être activée avec l'indicateur de configuration audioUseHalDuckingSignals :

<!-- Configuration to enable IAudioControl#onDevicesToDuckChange API to
inform HAL when to duck. If this is set to true, the API will receive signals
indicating which output devices to duck as well as what usages are currently
holding focus. If set to false, the API will not be called. -->
<bool name="audioUseHalDuckingSignals">true</bool>

Pour activer la fonctionnalité, le contrôle audio AIDL HAL doit implémenter la logique appropriée avec le signal reçu du service audio de la voiture :

interface IAudioControl {
       /**
       *   Notifies HAL of changes in output devices that the HAL should apply
       *   ducking to.
       *
       *   This will be called in response to changes in audio focus, and will
       *   include a {@link DuckingInfo} object per audio zone that experienced
       *   a change in audo focus.
       *
       *   @param duckingInfos an array of {@link DuckingInfo} objects for the
       *   audio zones where audio focus has changed.
       */
       oneway void onDevicesToDuckChange(in DuckingInfo[] duckingInfos);
}

Les informations pertinentes du système audio sont contenues dans les informations d'atténuation audio :

parcelable DuckingInfo {
       /**
       *   ID of the associated audio zone
       */
       int zoneId;
       /**
       *   List of addresses for audio output devices that should be ducked.
       */
       String[] deviceAddressesToDuck;
       /**
       *   List of addresses for audio output devices that were previously be
       *   ducked and should now be unducked.
       */
       String[] deviceAddressesToUnduck;
       /**
       *   List of usages currently holding focus for this audio zone.
       */
       String[] usagesHoldingFocus;
}

Outre les informations de configuration audio de la voiture contenues dans les adresses des appareils pour (un) canarder, les informations de canardage contiennent également des informations sur les utilisations des attributs audio qui sont prioritaires. L'objectif de ces données est d'informer le système audio quelles utilisations d'attributs audio sont actives.

Ceci est nécessaire car, dans la configuration audio de la voiture, plusieurs attributs audio peuvent être attribués à un seul appareil et, sans informations supplémentaires, il n'est pas clair quelles utilisations sont actives.

Contrôle audio AIDL HAL 2.0

Pour mettre à jour les API et faciliter les nouvelles fonctionnalités, le contrôle audio AIDL HAL a été mis à jour vers la version 2.0 dans Android 13 :

  • Focus audio avec PlaybackTrackMetadata
  • Rappel des gains audio

Les métadonnées de lecture sont définies dans android.hardware.audio.common comme suit :

parcelable PlaybackTrackMetadata {
       AudioUsage usage = INVALID;
       AudioContentType contentType = UNKNOWN;
       float gain;
       AudioChannelLayout channelMask;
       AudioDevice sourceDevice;
       String[] tags;
}

Toutes les autres fonctionnalités de la version 1.0 du contrôle audio AIDL sont restées et peuvent être utilisées. Une exception concerne la méthode de changement de focus audio, comme décrit dans Sur la méthode de changement de focus audio .

Focus sur le contrôle audio avec les métadonnées de la piste de lecture

Pour exposer plus d'informations au système audio sous le HAL, les mises à jour exposent désormais PlaybackTrackMetadata . Plus précisément, le contrôle audio HAL a été étendu avec une nouvelle méthode :

interface IAudioControl {
       /**
       *   Notifies HAL of changes in audio focus status for focuses requested
       *   or abandoned by the HAL.
       *
       *   The HAL is not required to wait for a callback of AUDIOFOCUS_GAIN
       *   before playing audio, nor is it required to stop playing audio in the
       *   event of a AUDIOFOCUS_LOSS callback is received.
       *
       *   @param playbackMetaData The output stream metadata associated with
       *    the focus request
       *   @param zoneId The identifier for the audio zone that the HAL is
       *    playing the stream in
       *   @param focusChange the AudioFocusChange that has occurred.
       */
       oneway void onAudioFocusChangeWithMetaData(
       in PlaybackTrackMetadata playbackMetaData, in int zoneId,
       in AudioFocusChange focusChange);
}

Une modification similaire et correspondante est apportée à IFocusListener :

       /**
       *   Called to indicate that the audio output stream associated with
       *   {@link android.hardware.audio.common.PlaybackTrackMetadata} is
       *   abandoning focus as playback has stopped.
       *
       *   @param playbackMetaData The output stream metadata associated with
       *    the focus request
       *   @param zoneId The identifier for the audio zone that the HAL
       *    abandoning focus
       */
       oneway void abandonAudioFocusWithMetaData(
       in PlaybackTrackMetadata playbackMetaData, in int zoneId);
       /**
       *   Called to indicate that the audio output stream associated with
       *   {@link android.hardware.audio.common.PlaybackTrackMetadata} has taken
       *   the focus as playback is starting for the corresponding stream.
       *
       *   @param playbackMetaData The output stream metadata associated with
       *    the focus request
       *   @param zoneId The identifier for the audio zone that the HAL
       *    abandoning focus
       *   @param focusGain The focus type requested.
       */
       oneway void requestAudioFocusWithMetaData(
       in PlaybackTrackMetadata playbackMetaData, in int zoneId,
       in AudioFocusChange focusGain);
}

Sur la méthode de changement de focus audio

Les opérations de focus ci-dessus s'effectuent de la même manière que celles décrites dans Demande de focus audio de HAL . Seules les métadonnées de la piste de lecture contiennent plus d'informations ainsi que les utilisations des attributs audio. En général, à moins que les informations supplémentaires fournies par les métadonnées de la piste de lecture ne soient nécessaires, le contrôle Android HAL mis à jour peut continuer à utiliser les méthodes précédentes.

Si les développeurs HAL décident de ne pas prendre en charge IAudioControl#onAudioFocusChangeWithMetaData , la méthode doit renvoyer des résultats avec l'erreur UNKNOWN_TRANSACTION comme décrit à l'aide des méthodes d'interface versionnées .

Le service audio appelle d'abord onAudioFocusChangeWithMetaData , puis réessaye avec la méthode onAudioFocusChange en cas d'échec UNKNOWN_TRANSACTION .

Ducking audio de voiture avec métadonnées de piste de lecture

La version 2.0 du contrôle audio AIDL HAL a ajouté les métadonnées de la piste de lecture aux informations de ducking audio :

parcelable DuckingInfo {
       /**
       *   ID of the associated audio zone
       */
       int zoneId;
       /**
       *   List of addresses for audio output devices that should be ducked.
       */
       String[] deviceAddressesToDuck;
       /**
       *   List of addresses for audio output devices that were previously be
       *   ducked and should now be unducked.
       */
       String[] deviceAddressesToUnduck;
       /**
       *   List of usages currently holding focus for this audio zone.
       */
       String[] usagesHoldingFocus;
       /**
       *   List of output stream metadata associated with the current focus
       *   holder for this audio zone
       */
       @nullable PlaybackTrackMetadata[] playbackMetaDataHoldingFocus;
}

usagesHoldingFocus est obsolète. Les développeurs doivent désormais utiliser playbackMetaDataHoldingFocus pour déterminer l'utilisation des attributs audio et d'autres informations audio. Cela dit, le paramètre usagesHoldingFocus contient toujours les informations requises jusqu'à ce que cette option soit formellement supprimée.

Rappel du gain audio

Pour rendre les modifications audio sous le HAL plus visibles pour l'AAOS dans Android 13, nous avons ajouté un mécanisme que vous pouvez utiliser pour communiquer les modifications des gains audio du système audio de la voiture au service audio de la voiture. Le mécanisme expose les modifications de l'indice de volume du gain audio avec une raison respective pour laquelle le gain a été modifié :

  • Restrictions bloquées ou désactivées
  • Restrictions
  • Restrictions d'atténuation

Ces modifications exposent ces restrictions situées sous le HAL au service audio de la voiture et, enfin, à une application d'interface utilisateur système pour informer l'utilisateur. Cette dernière partie, l'exposition à une éventuelle interface utilisateur système, a été encore étendue dans Android 14 pour permettre aux applications d'interface utilisateur système d'obtenir plus facilement ces informations via un mécanisme de rappel d'informations sur les groupes de volumes.

L'API HAL de contrôle audio enregistre le rappel de gain comme suit :

interface IAudioControl {
       /**
       *   Registers callback to be used by HAL for reporting unexpected gain(s)
       *    changed and the reason(s) why.
       *
       *   @param callback The {@link IAudioGainCallback}.
       */
       oneway void registerGainCallback(in IAudioGainCallback callback);
}

Le IAudioGainCallback est défini comme suit :

interface IAudioGainCallback {
       /**
       *   Used to indicate that one or more audio device port gains have changed,
       *   i.e. initiated by HAL, not by CarAudioService.
       *   This is the counter part of the
       *   {@link onDevicesToDuckChange}, {@link onDevicesToMuteChange} and,
       *   {@link setAudioDeviceGainsChanged} APIs.
       *
       *   @param reasons List of reasons that triggered the given gains changed.
       *   @param gains List of gains affected by the change.
       */
       void onAudioDeviceGainsChanged(in Reasons[] reasons,
       in AudioGainConfigInfo[] gains);
}

Comme souligné dans la documentation de l'API, le rappel de gain est enregistré par le service audio de la voiture auprès du HAL de contrôle audio. Lorsque l'API est appelée depuis le HAL de contrôle audio, le service audio de la voiture répond avec une action correspondante (telle que bloquer, limiter ou atténuer l'indice de gain).

Le HAL détermine le moment où l'API est appelée, principalement pour signaler les modifications apportées à l'état de l'index de gain. Spécifique aux exigences réglementaires, le système audio de la voiture doit prendre les mesures requises et utiliser le rappel pour signaler des informations au service audio de la voiture afin de permettre la consommation de l'utilisateur. Par exemple, pour afficher une interface utilisateur à l'utilisateur.

Contrôle audio AIDL HAL 3.0

La version HAL de contrôle audio Android 14 AIDL est mise à jour vers la version 3.0 pour mettre à jour les API afin de fournir une fonctionnalité d'index de gain audio plus robuste. L'API HAL de contrôle audio permet au service audio d'activer et de désactiver un IModuleChangeCallback :

interface IAudioControl {
       /**
       *   Sets callback with HAL for notifying changes to hardware module
       *   (that is: {@link android.hardware.audio.core.IModule}) configurations.
       *
       *   @param callback The {@link IModuleChangeCallback} interface to use
       *    use when new updates are available for
       */
       void setModuleChangeCallback(in IModuleChangeCallback callback);
       /**
       *   Clears module change callback
       */
       void clearModuleChangeCallback();
}

Le setModuleChangeCallback est enregistré par le service audio de la voiture lorsque le service démarre ou lors de la récupération après une erreur. Par exemple, une notification de décès de classeur HAL de contrôle audio reçue par le service audio de la voiture. L'implémentation du contrôle audio HAL doit remplacer tout rappel de changement de module existant lorsque l'API est appelée.

Pour l'API clearModuleChangeCallback , l'implémentation doit effacer le rappel existant ou ne rien faire s'il n'en existe pas. C'est une bonne pratique pour l'implémentation du contrôle audio d'enregistrer un observateur de mort pour le rappel, puis d'effacer le rappel si la mort du classeur est déclenchée.

IModuleChangeCallback est défini comme suit :

oneway interface IModuleChangeCallback {
       /**
       *   Used to indicate that one or more {@link AudioPort} configs have
       *   changed. Implementations MUST return at least one AudioPort.
       *
       *   @param audioPorts list of {@link AudioPort} that are updated
       */
       void onAudioPortsChanged(in AudioPort[] audioPorts);
}

Lorsque le rappel de changement de module est enregistré par le service audio de la voiture, il est prêt à recevoir les modifications de port audio via l'API onAudioPortChanged . L'API peut être utilisée pour initialiser les gains de volume du système audio dès que le rappel est enregistré. Pour d'autres modifications de gain dynamique, l'API peut être appelée à tout moment. Les modifications correspondantes sont appliquées et le service audio de la voiture est mis à jour en conséquence.