Commandes audio HAL

Le HAL de contrôle audio a été introduit dans Android 9 pour prendre en charge les cas d'utilisation audio pertinents pour l'automobile. À partir d'Android 14, le HAL de contrôle audio est compatible avec les éléments suivants:

  • Fondu et équilibre
  • Demande de priorité audio HAL
  • Couper le son de l'appareil et baisser le volume
  • Modifications du gain de l'appareil audio
  • Modifications de la configuration des ports audio

La figure 1 présente une vue d'ensemble de l'architecture du service audio de la voiture, dans laquelle le service audio de la voiture communique avec le HAL de contrôle audio.

Configurer l'audio multizone

Figure 1 : Configurez l'audio multizone.

Fondu sonore et balance audio

La version 1 de la HAL de contrôle audio HIDL a été introduite dans Android 9 pour prendre en charge le fondu et l'équilibre audio dans les cas d'utilisation automobile. En plus 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 de la faire fondre 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 à partir du 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 HAL de contrôle audio, y compris la nouvelle interface HAL AIDL.

Demande de priorité audio de la part de HAL

Comme Android, AAOS s'appuie sur la participation active des applications sur la mise au point audio pour gérer la lecture audio dans les voitures. Les informations de focus permettent de gérer les flux à contrôler pour le volume et le masquage. Par conséquent, pour élargir davantage la focalisation audio et améliorer l'intégration des sons spécifiques aux voitures dans l'expérience Android, les attributs audio suivants ont été introduits dans Android 11:

  • EMERGENCY
  • SAFETY
  • VEHICLE_STATUS
  • ANNOUNCEMENT

En plus de cette modification, un mécanisme a été ajouté pour que les sons provenant de l'extérieur d'Android puissent participer aux requêtes de mise au point audio. Par conséquent, la version 2 de la HAL de contrôle audio HIDL a été introduite pour permettre les requêtes de mise au point 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 suit:

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 pour demander et abandonner la sélection audio de la part du HAL, respectivement. En réponse, le service audio de la voiture prend en compte la requête de mise au point audio et transfère les résultats de manière asynchrone à la méthode IAudioControl#onAudioFocusChange.

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

Migrer HIDL vers le HAL de contrôle audio AIDL

Avec l'avènement d'AIDL et la migration requise dans Android 12 (pour en savoir plus, consultez AIDL pour les HAL), le HAL de contrôle audio a été migré vers AIDL. Pour les API HIDL de contrôle audio de la 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);
}

Désactivation du son du groupe de volumes

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

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

<!-- 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 écrasée par une superposition de ressources d'exécution pour packages/services/Car/service/res/values/config.xml (pour en savoir plus, consultez la section Personnaliser la compilation avec des superpositions de ressources). À partir d'Android 13, vous pouvez utiliser des 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 HAL de contrôle audio AIDL 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 masquage contiennent les informations pertinentes sur le masquage 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 propose deux mécanismes de mise en sourdine différents, en fonction de:

  • Événements de touche à l'aide de l'audio KEYCODE_VOLUME_MUTE.

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

Lorsqu'ils sont activés, les deux mécanismes déclenchent le masquage d'un appel dans le HAL de contrôle audio.

Atténuation audio de la voiture

Android 12 a introduit la réduction du volume audio de la voiture pour optimiser le contrôle de la lecture simultanée de flux audio. Cela permet aux OEM d'implémenter leur propre comportement de masquage en fonction de la configuration audio physique d'une voiture et de l'état de lecture actuel, tel que déterminé par le service audio de la voiture.

Le mécanisme de masquage est basé sur les modifications apportées à la pile de mise au point audio. Chaque fois qu'un changement de mise au point se produit (qu'il s'agisse d'une demande de mise au point ou d'un abandon de mise au point), le HAL de contrôle audio en est informé. Comme pour la prise en charge du masquage du volume du groupe de voitures, le masquage audio de la voiture peut être activé 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 cette fonctionnalité, le HAL de contrôle audio AIDL 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 sur le système audio sont contenues dans les informations de masquage 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;
}

En plus des informations de configuration audio de la voiture contenues dans les adresses de l'appareil pour (dé)masquer, les informations de masquage contiennent également des informations sur les utilisations des attributs audio qui maintiennent la sélection. L'objectif de ces données est d'indiquer au système audio les utilisations des attributs audio qui sont actives.

Cela est nécessaire, car dans la configuration audio de la voiture, plusieurs attributs audio peuvent être attribués à un seul appareil. Sans informations supplémentaires, il n'est pas clair quels usages sont actifs.

HAL 2.0 de contrôle audio AIDL

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

  • Priorité 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 de la commande audio AIDL sont conservées et peuvent être utilisées. Une exception concerne la méthode de changement de focus audio, comme décrit dans la section À propos de la méthode de changement de focus audio.

Contrôler la mise au point 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 HAL de contrôle audio 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);
}

Méthode de modification de la priorité audio

Les opérations de mise au point ci-dessus fonctionnent de la même manière que celles décrites dans la section Demande de mise au point audio de HAL. Seules les métadonnées du titre de lecture contiennent plus d'informations, ainsi que les utilisations des attributs audio. En général, sauf si les informations supplémentaires fournies par les métadonnées de la piste de lecture sont nécessaires, le HAL de contrôle Android 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 dans la section Utiliser des méthodes d'interface versionnées.

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

Masquage audio de la voiture avec les métadonnées de la piste de lecture

La version 2.0 du HAL de contrôle audio AIDL a ajouté les métadonnées de la piste de lecture aux informations de masquage 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;
}

Abandon de usagesHoldingFocus. Les développeurs doivent désormais utiliser playbackMetaDataHoldingFocus pour déterminer l'utilisation de l'attribut audio et d'autres informations audio. Toutefois, le paramètre usagesHoldingFocus contient toujours les informations requises jusqu'à ce que cette option soit officiellement supprimée.

Rappel de 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 de gain 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 la raison pour laquelle le gain a été modifié:

  • Restrictions de blocage ou de masquage
  • Limites
  • Restrictions d'atténuation

Ces modifications exposent ces restrictions en dessous du HAL au service audio de la voiture et, enfin, à une application d'UI système pour informer l'utilisateur. La dernière partie, l'exposition à une UI système possible, a été étendue dans Android 14 pour permettre aux applications d'UI système d'obtenir plus facilement ces informations via un mécanisme de rappel d'informations sur le groupe 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);
}

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 indiqué dans la documentation de l'API, le rappel de gain est enregistré par le service audio de la voiture dans le HAL de contrôle audio. Lorsque l'API est appelée à partir du HAL de contrôle audio, le service audio de la voiture répond avec une action correspondante (par exemple, bloquer, limiter ou atténuer l'indice de gain) .

Le HAL détermine quand l'API est appelée, principalement pour signaler les modifications apportées à l'état de l'indice de gain. Conformément aux exigences réglementaires, le système audio de la voiture doit prendre les mesures requises et utiliser le rappel pour transmettre des informations au service audio de la voiture afin de permettre la consommation par l'utilisateur. Par exemple, pour afficher une UI à l'utilisateur.

HAL 3.0 de contrôle audio AIDL

La version 3.0 de la HAL de contrôle audio AIDL Android 14 est mise à jour pour mettre à jour les API afin de fournir une fonctionnalité d'indice de gain audio plus robuste. L'API HAL de contrôle audio permet au service audio de définir et de supprimer 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();
}

setModuleChangeCallback est enregistré par le service audio de la voiture au démarrage du service ou lors de la récupération d'une erreur. Par exemple, une notification de fin de liaison HAL de contrôle audio reçue par le service audio de la voiture. L'implémentation du HAL de contrôle audio doit remplacer tout rappel de modification 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'existe pas. Il est recommandé que l'implémentation de la commande audio enregistre un observateur de fin pour le rappel, puis efface le rappel si le rappel de fin du liaisonneur est déclenché.

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 modification du module est enregistré par le service audio de la voiture, il est prêt à recevoir les modifications du 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 les 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.