Перед запуском логического потока приложение должно запросить аудиофокус, используя те же аудиоатрибуты, которые оно будет использовать для своего логического потока. Хотя отправка такого запроса на фокусировку рекомендуется, она не применяется системой. Некоторые приложения могут явно пропускать отправку запроса для достижения определенного поведения (например, для преднамеренного воспроизведения звука во время телефонного звонка).
По этой причине вы должны рассматривать фокус как способ косвенного управления воспроизведением и устранения конфликтов, а не как основной механизм управления звуком; автомобиль не должен зависеть от системы фокусировки для работы аудиоподсистемы.
Фокус взаимодействия
Для поддержки потребностей AAOS запросы фокуса звука обрабатываются на основе предопределенных взаимодействий между CarAudioContext
запроса и текущими держателями фокуса. Существует три типа взаимодействия: исключающее, отклоненное и параллельное.
Эксклюзивное взаимодействие
В эксклюзивных взаимодействиях только одно приложение может удерживать фокус одновременно. Поэтому входящий запрос фокуса получает фокус, в то время как существующий держатель фокуса теряет фокус. Примером этого может быть случай, когда пользователь запускает новое музыкальное приложение, в то время как музыка уже воспроизводится в существующем приложении. Поскольку оба воспроизводят мультимедиа, только одно из приложений может одновременно удерживать фокус. В результате запрос фокуса только что запущенного приложения вернется с AUDIOFOCUS_REQUEST_GRANTED
а приложение, в настоящее время воспроизводящее музыку, получит событие изменения фокуса со статусом потери, соответствующим типу сделанного запроса. Это модель взаимодействия, наиболее часто встречающаяся в Android.
Отклонить взаимодействие
При отклонении взаимодействия входящий запрос всегда отклоняется. Попытка воспроизвести музыку во время разговора является примером отклоненного взаимодействия. В этом случае, если номеронабиратель в настоящее время удерживает фокус звука для вызова, а второй запрос приложения фокусируется на воспроизведении музыки, музыкальное приложение получит AUDIOFOCUS_REQUEST_FAILED
в ответ на свой запрос. Поскольку запрос на фокус отклонен, никакая потеря фокуса любого типа не отправляется текущему владельцу фокуса.
Параллельное взаимодействие
Наиболее уникальными для AAOS являются одновременные взаимодействия. Это дает приложениям, запрашивающим фокусировку звука в автомобиле, возможность удерживать фокусировку одновременно с другими приложениями. Для одновременного взаимодействия должны быть выполнены следующие условия. В:
- Входящий запрос фокуса должен запрашивать
AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
. - Текущий держатель фокуса не
setPauseWhenDucked(true)
. - Текущий держатель фокуса не хочет получать события «утка».
Если эти критерии соблюдены, то запрос фокуса вернется с AUDIOFOCUS_REQUEST_GRANTED
, в то время как у текущего держателя фокуса не будет изменения фокуса. Однако, если текущий владелец фокуса решит получать события приседания или сделать паузу при приседании, текущий держатель фокуса потеряет фокус, как и в случае эксклюзивного взаимодействия.
Обработка параллельных потоков
Хотя параллельное взаимодействие имеет много полезных применений, OEM-производители должны позаботиться о микшировании и дакинге на аппаратном уровне для устройств вывода. По этой причине настоятельно рекомендуется, чтобы CarAudioContext
направлялись только на то же устройство вывода, что и CarAudioContext
, с которыми они не могут воспроизводиться одновременно. Наличие отдельных устройств вывода для параллельных потоков позволяет HAL отключать один из потоков перед их смешиванием или направлять физические потоки на разные динамики в автомобиле. Если логические потоки смешаны в Android, их выигрыши не изменятся, и они будут доставлены как часть одного и того же физического потока.
Например, когда навигация и мультимедиа доставляются одновременно, усиление для медиапотока может быть временно уменьшено (приглушено), чтобы навигационные инструкции были слышны более четко. В качестве альтернативы навигационный поток может быть направлен на динамики со стороны водителя, в то время как медиафайлы продолжают воспроизводиться в остальной части салона.
Матрица взаимодействия
В таблице ниже показана матрица взаимодействия, определенная CarAudioService
. Строки представляют собой CarAudioContext
текущего держателя фокуса, а столбцы представляют контекст входящего запроса.
Глядя на пример, где музыкальное мультимедийное приложение в настоящее время удерживает фокус, а фокус запроса приложения навигации, матрица показывает, что два взаимодействия могут воспроизводиться одновременно, при условии, что другие критерии для одновременных взаимодействий соблюдены.
Из-за параллельных взаимодействий возможно существование более одного держателя фокуса. В этом случае входящий запрос на фокус будет сравниваться с каждым из текущих держателей фокуса, прежде чем будет принято решение о том, какое взаимодействие применить. В этом случае побеждает наиболее консервативное взаимодействие (отклоняющее, затем исключающее и, наконец, параллельное).
В следующей таблице представлены взаимодействия фокуса между CarAudioContext для входящего запроса фокуса (столбцы) и контекстом существующих держателей фокуса (строки). Каждая ячейка представляет ожидаемый тип взаимодействия для двух контекстов, где:
- R: Отклонить взаимодействие
- E: Эксклюзивное взаимодействие
- C: Параллельное взаимодействие
Рисунок 1. Взаимодействие фокуса звука
Навигация во время телефонных звонков
В Android 11 была введена новая пользовательская настройка, позволяющая пользователям изменять взаимодействие между навигацией и телефонными звонками. Когда установлено, android.car.KEY_AUDIO_FOCUS_NAVIGATION_REJECTED_DURING_CALL
изменит взаимодействие между входящими запросами фокуса NAVIGATION
и текущими держателями фокуса CALL
с одновременного на отклонение . Поэтому, если пользователь не хочет, чтобы инструкции по навигации прерывали его вызов, он может включить этот параметр. Это сохраняется для пользователя и может быть установлено динамически, чтобы последующие запросы фокуса учитывали новое значение параметра.
Отложенный звуковой фокус
В Android 11 AAOS добавила поддержку запроса аудиофокуса с задержкой. Это позволяет откладывать невременные запросы фокуса, когда их взаимодействие с текущими держателями фокуса обычно приводит к их отклонению. Как только изменение фокуса приводит к состоянию, в котором отложенный запрос может получить фокус, запрос будет удовлетворен.
Правила для отложенных запросов фокуса звука
- Только невременные запросы — как упоминалось ранее, отложенный запрос может быть сделан только для невременных источников. Это делается для того, чтобы не воспроизводиться переходный звук спустя долгое время после того, как он стал актуальным.
- Одновременно может быть отложен только один запрос. Если отложенный запрос сделан, когда уже есть отложенный запрос, исходный отложенный запрос получит событие изменения
AUDIOFOCUS_LOSS
, а новый запрос получит синхронный ответAUDIOFOCUS_REQUEST_DELAYED
. - Отложенные запросы должны иметь
OnAudioFocusChangeListener
. Как только запрос задерживается, прослушиватель будет использоваться для уведомления запрашивающего, когда запрос в конечном итоге будет удовлетворен (AUDIOFOCUS_GAIN
) или если он будет отклонен позже (AUDIOFOCUS_LOSS
).
Запрос отложенного фокуса
Чтобы создать запрос, который можно отложить, используйте AudioFocusRequest.Builder#setAcceptsDelayedFocusGain
:
mMediaWithDelayedFocusListener = new MediaWithDelayedFocusListener(); mDelayedFocusRequest = new AudioFocusRequest .Builder(AudioManager.AUDIOFOCUS_GAIN) .setAudioAttributes(mMusicAudioAttrib) .setOnAudioFocusChangeListener(mMediaWithDelayedFocusListener) .setForceDucking(false) .setWillPauseWhenDucked(false) .setAcceptsDelayedFocusGain(true) .build();
Затем при выполнении запроса обработайте ответ AUDIOFOCUS_REQUEST_DELAYED
:
int delayedFocusRequestResults = mAudioManager.requestAudioFocus(mDelayedFocusRequest); if (delayedFocusRequestResults == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) { // start audio playback return; } if (delayedFocusRequestResults == AudioManager.AUDIOFOCUS_REQUEST_DELAYED) { // audio playback delayed to audio focus listener return; }
Когда запрос задерживается, прослушиватель фокуса отвечает за обработку изменений в фокусе:
private final class MediaWithDelayedFocusListener implements OnAudioFocusChangeListener { @Override public void onAudioFocusChange(int focusChange) { synchronized (mLock) { switch (focusChange) { case AudioManager.AUDIOFOCUS_GAIN: … // Start focus playback case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT: … // Pause media transiently case AudioManager.AUDIOFOCUS_LOSS: … // Stop media
Управление многозонным фокусом
Для автомобилей с несколькими аудиозонами аудиофокус будет управляться отдельно для каждой зоны. Таким образом, запрос к одной зоне не будет учитывать то, что удерживает фокус в других зонах, и не приведет к потере фокуса держателями фокуса в других зонах. При этом фокусом основной кабины можно управлять отдельно от развлекательной системы для пассажиров задних сидений, что позволяет избежать прерывания воспроизведения звука в одной зоне из-за изменения фокуса в другой.
CarAudioService
автоматически управляет фокусом для всех приложений. Аудиозона запроса фокуса определяется на основе связанного с ней UserId
или UID
. Дополнительные сведения см. в разделе Маршрутизация аудио .
Запрос звука из нескольких зон одновременно
Если приложение хочет одновременно воспроизводить звук в нескольких зонах, оно должно запросить фокус для каждой зоны, включив AUDIOFOCUS_EXTRA_REQUEST_ZONE_ID
в пакет:
//Create attribute with bundle and AUDIOFOCUS_EXTRA_REQUEST_ZONE_ID Bundle bundle = new Bundle(); bundle.putInt(CarAudioManager.AUDIOFOCUS_EXTRA_REQUEST_ZONE_ID, zoneId); AudioAttributes attributesWithZone = new AudioAttributes.Builder() .setUsage(AudioAttributes.USAGE_MEDIA) .addBundle(bundle) .build(); //Create focus request using built attributesWithZone
Этот параметр пакета позволяет инициатору запроса переопределить автоматические сопоставления аудиозон, чтобы вместо этого использовать указанный идентификатор зоны. Следовательно, при этом приложение может выдавать отдельные запросы для разных аудиозон.
HAL Аудио Фокус
Начиная с Android 11, HAL теперь может запрашивать фокус от имени внешних потоков. Хотя эти API необязательны, настоятельно рекомендуется использовать внешние звуки, чтобы они лучше участвовали в экосистеме Android и обеспечивали более плавный пользовательский интерфейс.
Имейте в виду, что HAL по-прежнему отвечает за принятие окончательного решения о том, какие звуки должны иметь приоритет. В этой связи аварийные и важные для безопасности звуки должны воспроизводиться независимо от того, предоставлен ли HAL звуковой фокус или нет, и должны продолжать воспроизводиться соответствующим образом, даже если HAL теряет звуковой фокус. То же самое верно для любых звуков, требуемых правилами.
В том же духе HAL должен по-прежнему заблаговременно отключать потоки Android, когда это необходимо, при воспроизведении аварийных или критических звуков, чтобы обеспечить их четкую слышимость.
Аудиоконтроль@2.0
Версия 2.0 AudioControl HAL представляет несколько новых API:
API | Цель |
---|---|
IAudioControl#registerFocusListener | Регистрирует экземпляр IFocusListener в AudioControl HAL. Этот прослушиватель позволяет HAL запрашивать аудиофокус и отказываться от него. Ожидается, что HAl предоставит экземпляр ICloseHandle , который будет использоваться Android для отмены регистрации прослушивателя. |
IAudioControl#onAudioFocusChange | Уведомляет HAL об изменениях статуса, чтобы сфокусировать запросы, сделанные HAL через IFocusListener . Это включает в себя ответы на первоначальные запросы фокуса. |
IFocusListener#requestAudioFocus | Запросы фокусируются от имени HAL для указанного использования, идентификатора зоны и типа усиления фокуса. |
IFocusListener#abandonAudioFocus | Отказывается от существующих запросов фокуса HAL для указанного использования и идентификатора зоны. |
HAL может иметь несколько запросов фокуса одновременно, но ограничен одним запросом на использование и пару идентификаторов зон. Обратите внимание, что Android предполагает, что HAL немедленно начнет воспроизводить звуки для использования после того, как запрос был сделан, и будет продолжать это делать, пока не потеряет фокус.
За исключением registerFocusListener
, все эти запросы являются oneway
, чтобы гарантировать, что Android не задерживает HAL во время обработки запроса фокуса. HAL не должен ждать, чтобы сфокусироваться, прежде чем воспроизводить критические для безопасности звуки. Для HAL необязательно прослушивать и реагировать на изменения фокуса звука с помощью IAudioControl#onAudioFocusChange
, хотя это рекомендуется, когда это уместно.