В Android 9 был представлен Audio control HAL для поддержки сценариев использования звука, актуальных для автомобильной промышленности. Начиная с Android 14, Audio control HAL поддерживает:
- Затухание и баланс
- Запрос на фокусировку звука HAL
- Отключение звука и приглушение звука устройства
- изменения усиления аудиоустройства
- изменения конфигурации аудиопорта
На рисунке 1 представлен общий обзор архитектуры сервиса автомобильной аудиосистемы, в которой сервис автомобильной аудиосистемы взаимодействует с HAL управления аудиосистемой.

Рисунок 1. Настройка многозонного звука.
Затухание звука и баланс
В Android 9 была представлена версия 1 HAL управления звуком HIDL для поддержки регулировки баланса звука в автомобильной среде. Помимо стандартных звуковых эффектов, уже имеющихся в 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, в запросах на фокусировку звука. Таким образом, была представлена версия 2 HAL управления звуком HIDL, позволяющая обрабатывать запросы на фокусировку, исходящие извне 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-модулю управления звуком получать события отключения звука, перехваченные службой автомобильной аудиосистемы.
Для включения этой функции производители автомобилей должны установить параметр audioUseCarVolumeGroupMuting в true в файле car service 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 появилась функция автоматического приглушения звука в автомобиле, позволяющая оптимизировать управление одновременным воспроизведением аудиопотоков. Это дает производителям автомобилей возможность реализовать собственное поведение приглушения звука в зависимости от физической конфигурации аудиосистемы автомобиля и текущего состояния воспроизведения, определяемого службой автомобильной аудиосистемы.
Механизм приглушения звука основан на изменениях стека фокусировки звука. При каждом изменении фокуса (будь то запрос фокусировки или отказ от фокусировки) 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 и расширения функциональности в Android 13 интерфейс управления звуком AIDL был обновлен до версии 2.0:
- Фокусировка на звуке с помощью
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» . Только метаданные воспроизводимого трека содержат больше информации, помимо используемых атрибутов аудио. В целом, если дополнительная информация, предоставляемая метаданными воспроизводимого трека, не требуется, обновленный Android-контроллер HAL может продолжать использовать предыдущие методы.
Если разработчики HAL решат не поддерживать IAudioControl#onAudioFocusChangeWithMetaData , он должен возвращать результаты с ошибкой UNKNOWN_TRANSACTION как описано в разделе «Использование методов версионированного интерфейса» .
Аудиосервис сначала вызывает метод onAudioFocusChangeWithMetaData , а затем повторяет попытку с помощью метода onAudioFocusChange , если возникает ошибка UNKNOWN_TRANSACTION .
Приглушение автомобильной аудиосистемы с использованием метаданных воспроизводимого трека
В версии 2.0 HAL управления звуком AIDL к информации о подавлении звука были добавлены метаданные воспроизводимой дорожки:
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 для определения использования аудиоатрибутов и другой аудиоинформации. Тем не менее, параметр 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
В Android 14 версия HAL управления звуком 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.
Для API clearModuleChangeCallback реализация должна очистить существующий коллбэк или ничего не делать, если его нет. Хорошей практикой для реализации управления звуком является регистрация наблюдателя завершения работы коллбэка и последующая очистка коллбэка при срабатывании события on binder death.
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 можно вызывать в любое время. Соответствующие изменения применяются, и служба автомобильной аудиосистемы обновляется соответствующим образом.