Аудио контроль HAL

Управление звуком HAL было представлено в Android 9 для поддержки случаев использования звука, имеющих отношение к автомобилям. Начиная с Android 14, управление звуком HAL поддерживает:

  • Исчезновение и баланс
  • Запрос фокусировки звука HAL
  • Отключение звука и приглушение устройства
  • Изменения усиления аудиоустройства
  • Изменения конфигурации аудиопорта

На рисунке 1 показан общий обзор архитектуры службы автомобильной аудиосистемы, в которой служба автомобильной аудиосистемы взаимодействует с HAL управления аудиосистемой.

Настройка многозонного звука

Рисунок 1. Настройка многозонного звука.

Затухание звука и баланс

Управление звуком HIDL HAL версии 1 было представлено в Android 9 для поддержки затухания и баланса звука в автомобильных приложениях. Помимо стандартных звуковых эффектов, уже представленных в Android, этот механизм позволяет системным приложениям устанавливать баланс звука и затухать с помощью 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);
}

После вызова этих API из службы автомобильной аудиосистемы вызываются соответствующие API-интерфейсы управления звуком HAL:

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);
}

API доступен во всех версиях HAL управления звуком, включая новый интерфейс AIDL HAL.

Запрос фокусировки звука от HAL

AAOS, как и Android, полагается на активное участие приложений, ориентированных на звук, для управления воспроизведением звука в автомобилях. Информация о фокусе используется для управления потоками, которые следует контролировать по громкости и приглушению. Таким образом, чтобы еще больше расширить акцент на звуке и обеспечить лучшую интеграцию звуков автомобиля в работу Android, в Android 11 были введены следующие атрибуты звука:

  • EMERGENCY
  • SAFETY
  • VEHICLE_STATUS
  • ANNOUNCEMENT

В дополнение к этому изменению был добавлен механизм для звуков, исходящих из-за пределов Android, для участия в запросах фокусировки звука. Таким образом, был введен HIDL-управление звуком HAL версии 2, позволяющее обрабатывать запросы фокуса, исходящие из-за пределов 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 определяется как:

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);
}

Вышеуказанные API можно использовать для запроса и отказа от фокуса звука из HAL соответственно. В ответ служба автомобильной аудиосистемы рассматривает запрос фокусировки звука и асинхронно передает результаты методу IAudioControl#onAudioFocusChange .

Этот API также можно использовать для отслеживания изменений запроса фокуса звука, исходящего из HAL управления звуком. В общем, любой постоянный запрос фокусировки звука от HAL считается активным , что отличается от запроса фокусировки звука от Android, в котором активным считается только соответствующее активное воспроизведение звуковой дорожки.

Миграция HIDL на AIDL для управления звуком HAL

С появлением AIDL и необходимой миграцией в Android 12 (более подробную информацию см. в разделе AIDL для HAL ) HAL для управления звуком был перенесен в AIDL. Для существующих API-интерфейсов управления звуком HIDL версии 2 миграция потребовала незначительных обновлений существующих методов:

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);
}

И соответствующий IFocusListener :

       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);
}

Отключение звука группы громкости

В Android 12 появилось групповое отключение звука, чтобы обеспечить более полное управление отключением звука во время аудиовзаимодействий пользователя. Это позволяет HAL управления аудиосистемой получать события отключения звука, перехваченные службой автомобильной аудиосистемы.

Чтобы включить эту функцию, OEM-производители должны установить для конфигурации audioUseCarVolumeGroupMuting значение true в 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>

До Android 13 конфигурацию приходилось перезаписывать наложением ресурсов времени выполнения для packages/services/Car/service/res/values/config.xml (более подробную информацию см. в разделе Настройка сборки с наложением ресурсов ). Начиная с Android 13, вы можете использовать наложения ресурсов среды выполнения для изменения значения конфигурации. Дополнительные сведения см. в разделе Изменение значения ресурсов приложения во время выполнения .

Системные приложения могут определить, включена ли эта функция, с помощью API CarAudioManager#isAudioFeatureEnabled . Передаваемый параметр должен быть константой CarAudioManager.AUDIO_FEATURE_VOLUME_GROUP_MUTING . Метод возвращает true , если эта функция включена на устройстве, в противном случае false .

Помимо включения функции audioUseCarVolumeGroupMuting , HAL управления звуком AIDL должен реализовать механизм отключения звука в группе:

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);
}

Если информация о выключении звука содержит соответствующую информацию об отключении звука для аудиосистемы:

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 имеет два разных механизма отключения звука, основанных на:

  • Ключевые события с использованием аудио KEYCODE_VOLUME_MUTE .

  • Прямые вызовы службы автомобильной аудиосистемы с использованием API отключения звука диспетчера автомобильной аудиосистемы CarAudioManager#setVolumeGroupMute .

При включении оба механизма запускают отключение звука вызова в HAL управления звуком.

Приглушение автомобильного звука

В Android 12 реализовано приглушение автомобильного звука для оптимизации управления одновременным воспроизведением аудиопотоков. Это позволяет OEM-производителям реализовать собственное поведение приглушения звука на основе физической конфигурации аудиосистемы автомобиля и текущего состояния воспроизведения, определяемого службой автомобильной аудиосистемы.

Механизм приглушения основан на изменениях стека аудиофокуса. Всякий раз, когда происходит изменение фокуса (будь то запрос на фокус или отказ от фокуса), об этом сообщается HAL управления звуком. Подобно поддержке отключения звука в группе громкости автомобиля, приглушение автомобильного звука можно включить с помощью флага конфигурации 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>

Чтобы включить эту функцию, HAL управления аудиосистемой AIDL должен реализовать соответствующую логику с сигналом, полученным от службы автомобильной аудиосистемы:

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);
}

Соответствующая информация об аудиосистеме содержится в информации о приглушении звука:

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;
}

Помимо информации о конфигурации автомобильной аудиосистемы, содержащейся в адресах устройства для (не)приглушения, информация о приглушении также содержит информацию о том, какие использования аудиоатрибутов удерживают фокус. Целью этих данных является информирование аудиосистемы о том, какие атрибуты аудио используются активно.

Это необходимо, поскольку в конфигурации автомобильной аудиосистемы одному устройству можно назначить несколько аудиоатрибутов, и без дополнительной информации неясно, какое использование активно.

Управление звуком AIDL HAL 2.0

Для обновления API и обеспечения новых функций HAL управления звуком AIDL был обновлен до версии 2.0 в Android 13:

  • Аудио фокус с PlaybackTrackMetadata
  • Звук получает обратный вызов

Метаданные воспроизведения определяются в android.hardware.audio.common следующим образом:

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

Все остальные функции управления звуком AIDL версии 1.0 остались и могут быть использованы. Исключение относится к методу изменения фокуса звука, как описано в разделе «Метод изменения фокуса звука» .

Фокус управления звуком с метаданными дорожки воспроизведения

Чтобы предоставить больше информации аудиосистеме ниже HAL, обновления теперь предоставляют PlaybackTrackMetadata . В частности, HAL управления звуком был расширен новым методом:

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);
}

Аналогичное соответствующее изменение внесено в 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);
}

О методе изменения фокуса звука

Вышеописанные операции фокусировки выполняются так же, как описано в разделе «Запрос фокусировки звука от HAL» . Только метаданные дорожки воспроизведения содержат дополнительную информацию, а также использование атрибутов звука. В общем, если не требуется дополнительная информация, предоставляемая метаданными дорожки воспроизведения, обновленный HAL элемента управления Android может продолжать использовать предыдущие методы.

Если разработчики HAL решат не поддерживать IAudioControl#onAudioFocusChangeWithMetaData , метод должен возвращать результаты с ошибкой UNKNOWN_TRANSACTION , как описано с использованием методов версионного интерфейса .

Служба аудио сначала вызывает onAudioFocusChangeWithMetaData , а затем повторяет попытку с помощью метода onAudioFocusChange , если возникает ошибка UNKNOWN_TRANSACTION .

Приглушение автомобильного звука с метаданными воспроизводимой дорожки

Версия 2.0 системы управления звуком AIDL HAL добавила метаданные воспроизводимой дорожки к информации о приглушении звука:

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 устарел. Теперь разработчикам следует использовать playbackMetaDataHoldingFocus для определения использования атрибута audio и другой аудиоинформации. Тем не менее, параметр usagesHoldingFocus по-прежнему содержит необходимую информацию до тех пор, пока этот параметр не будет формально удален.

Обратный вызов усиления звука

Чтобы сделать изменения звука ниже HAL более заметными для AAOS в Android 13, мы добавили механизм, который вы можете использовать для передачи изменений усиления звука из аудиосистемы автомобиля в службу автомобильной аудиосистемы. Механизм отображает изменения индекса громкости усиления звука с указанием соответствующей причины, по которой усиление было изменено:

  • Заблокированные или отключенные ограничения
  • Ограничения ограничения
  • Ограничения по затуханию

Эти изменения раскрывают эти ограничения ниже HAL для службы автомобильной аудиосистемы и, наконец, для приложения системного пользовательского интерфейса для информирования пользователя. Последняя часть, доступ к возможному системному пользовательскому интерфейсу, была дополнительно расширена в Android 14, чтобы позволить приложениям системного пользовательского интерфейса более легко получать эту информацию через механизм обратного вызова информации о группе томов.

API управления звуком HAL регистрирует обратный вызов усиления следующим образом:

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 определяется следующим образом:

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);
}

Как указано в документации API, обратный вызов усиления регистрируется службой автомобильной аудиосистемы в HAL управления звуком. Когда API вызывается из HAL управления звуком, служба автомобильной аудиосистемы отвечает соответствующим действием (например, блокировать, ограничивать или ослаблять индекс усиления).

HAL определяет, когда вызывается API, в первую очередь для сообщения об изменениях состояния индекса усиления. В соответствии с нормативными требованиями аудиосистема автомобиля должна предпринять необходимые действия и использовать обратный вызов для передачи информации в службу автомобильной аудиосистемы, чтобы позволить пользователю использовать ее. Например, чтобы показать пользователю пользовательский интерфейс.

Управление звуком AIDL HAL 3.0

Версия HAL для управления звуком Android 14 AIDL обновлена ​​до версии 3.0, чтобы обновить API-интерфейсы и обеспечить более надежную функциональность индекса усиления звука. API управления звуком HAL позволяет аудиосервису устанавливать и отключать 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 регистрируется службой автомобильной аудиосистемы при запуске службы или при восстановлении после ошибки. Например, уведомление о смерти связующего устройства HAL управления звуком, полученное службой автомобильной аудиосистемы. Реализация HAL управления звуком должна заменять любой существующий обратный вызов изменения модуля при вызове API.

Для clearModuleChangeCallback реализация должна очистить существующий обратный вызов или ничего не делать, если он не существует. Хорошей практикой для реализации управления звуком является регистрация наблюдателя смерти для обратного вызова, а затем очистка обратного вызова, если срабатывает смерть привязки.

IModuleChangeCallback определяется следующим образом:

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);
}

Когда обратный вызов изменения модуля регистрируется службой автомобильной аудиосистемы, она готова получать изменения аудиопорта через API onAudioPortChanged . API можно использовать для инициализации усиления громкости аудиосистемы сразу после регистрации обратного вызова. Для других динамических изменений усиления API можно вызвать в любое время. Соответствующие изменения применяются, и служба автозвука соответствующим образом обновляется.