Перед запуском логического потока приложение должно запросить фокус звука, используя те же атрибуты звука, которые используются для его логического потока. Хотя отправка такого запроса на фокусировку рекомендуется, она не применяется системой. Некоторые приложения могут явно пропускать отправку запроса для достижения определенного поведения (например, для намеренного воспроизведения звука во время телефонного звонка).
По этой причине вам следует рассматривать фокус как способ косвенного управления воспроизведением и устранения конфликтов, а не как основной механизм управления звуком; автомобиль не должен зависеть от системы фокусировки в работе аудиоподсистемы.
Фокус взаимодействия
Для удовлетворения потребностей 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 для входящего запроса фокуса (столбцы) и контекстом существующих держателей фокуса (строки). Каждая ячейка представляет ожидаемый тип взаимодействия для двух контекстов.
Рисунок 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
, хотя это рекомендуется, когда это необходимо.