Передача аудиовхода

Обычно аудиовход – это встроенный или внешний микрофон или аудиоинтерфейс, подключенный к устройству. Аудиовход также может поступать из телефонного разговора.

Иногда два или более приложений могут пытаться захватить один и тот же аудиовход. Они могут выполнять разные задачи. Например, некоторые приложения, получающие аудио, могут записывать его (как диктофон), а другие — слушать (как Google Ассистент или сервис специальных возможностей, реагирующий на голосовые команды).

В обоих случаях приложениям нужен доступ к аудиовходу. В этой статье мы используем термин "запись" независимо от того, записывает ли приложение звук или просто слушает.

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

Поведение в версиях до Android 10

До Android 10 входной аудиопоток могло записывать только одно приложение за раз. Если какое-либо приложение уже записывало или прослушивало аудио, ваше приложение могло создать объект AudioRecord, но при вызове AudioRecord.startRecording() возвращалась ошибка и запись не начиналась.

Исключением из этого правила были случаи, когда у привилегированного приложения (например, Google Ассистента или специальной возможности) было разрешение android.permission.CAPTURE_AUDIO_HOTWORD и оно использовало источник аудио типа HOTWORD. В этом случае запись может начать другое приложение. В этом случае привилегированное приложение закрывалось, а новое приложение перехватывало ввод.

В Android 9 было добавлено ещё одно изменение: только приложения, работающие в активном режиме (или активная служба), могут записывать аудиовход. Если приложение без активной службы или компонента интерфейса начинало запись, оно продолжало работать, но получало тишину, даже если было единственным приложением, записывающим аудио в этот момент.

Поведение в Android 10

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

В Android 10 используется схема приоритетов, которая может переключать входной аудиопоток между приложениями во время их работы. В большинстве случаев, если новое приложение получает доступ к аудиовходу, ранее записывавшее приложение продолжает работать, но получает тишину. В некоторых случаях система может продолжать передавать аудио в оба приложения. Ниже описаны различные сценарии предоставления доступа.

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

Для записи аудио Android различает два типа приложений:

  • "Обычные" приложения устанавливаются пользователем.
  • Привилегированные приложения предустановлены на устройстве. К ним относятся Google Ассистент и все специальные возможности.

Кроме того, приложение обрабатывается по-другому, если оно использует источник аудио, связанный с конфиденциальностью: CAMCORDER или VOICE_COMMUNICATION.

Приоритет использования и передачи аудиовхода определяется следующими правилами:

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

Сценарии предоставления доступа

Если два приложения пытаются записать аудио, они оба могут получить входной сигнал или одно из них может получить тишину.

Существует четыре основных сценария:

  • Ассистент + обычное приложение
  • Сервис специальных возможностей + обычное приложение
  • Два обычных приложения
  • Голосовой вызов + обычное приложение

Ассистент + обычное приложение

Ассистент – это привилегированное приложение, поскольку оно предустановлено и имеет роль RoleManager.ROLE_ASSISTANT. Любое другое предустановленное приложение с этой ролью обрабатывается аналогично.

Android предоставляет доступ к аудиовходу по следующим правилам:

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

  • Приложение получает аудио, если у Ассистента нет видимого компонента интерфейса в верхней части экрана.

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

Сервис специальных возможностей + обычное приложение

Для AccessibilityService требуется строгое объявление.

Android предоставляет доступ к входному аудио в соответствии со следующими правилами:

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

  • Если сервис не находится на переднем плане, этот случай обрабатывается как обычный случай с двумя приложениями, описанный ниже.

Два обычных приложения

Если два приложения одновременно записывают звук, только одно из них получает аудио, а другое – тишину.

Android предоставляет доступ к входному аудио в соответствии со следующими правилами:

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

Голосовой вызов + обычное приложение

Голосовой вызов активен, если режим аудио, возвращаемый AudioManager.getMode(), – MODE_IN_CALL или MODE_IN_COMMUNICATION.

Android предоставляет доступ к аудиовходу по следующим правилам:

Поведение в Android 11

В Android 11 (уровень API 30) используется схема приоритетов Android 10, описанная выше. Кроме того, в AudioRecord, MediaRecorder и AAudioStream появились новые методы, которые позволяют включать и отключать одновременную запись аудио независимо от выбранного варианта использования.

Новые методы:

Если для setPrivacySensitive() задано значение true, захват выполняется в частном режиме и даже привилегированный Ассистент не может выполнять его параллельно. Эта настройка переопределяет режим работы по умолчанию, который зависит от источника аудио. Например, VOICE_COMMUNICATION по умолчанию является частным, а UNPROCESSED – нет.

Изменения конфигурации

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

  • Устройство ввода аудио для каждого активного приложения может измениться (например, со встроенного микрофона на подключенную Bluetooth-гарнитуру).
  • Включается предварительная обработка, связанная с активным приложением с наивысшим приоритетом. Все остальные настройки предварительной обработки игнорируются.

Поскольку активное приложение может быть отключено, когда активируется приложение с более высоким приоритетом, вы можете зарегистрировать AudioManager.AudioRecordingCallback в объекте AudioRecord или MediaRecorder, чтобы получать уведомления об изменении конфигурации. Возможные изменения:

  • Запись со звуком или без
  • Устройство изменено
  • Изменена предварительная обработка
  • Изменились свойства потока (частота дискретизации, маска канала, формат выборки).

Вы должны вызвать AudioRecord.registerAudioRecordingCallback() до начала записи. Обратный вызов выполняется, только когда приложение получает аудио и происходит изменение.

Метод onRecordingConfigChanged() возвращает объект AudioRecordingConfiguration, содержащий текущее состояние записи аудио. Чтобы узнать больше об этом изменении, воспользуйтесь следующими методами:

isClientSilenced()
Возвращает значение true, если звук, возвращаемый клиенту, в настоящее время отключен из-за правил записи.
getAudioDevice()
Возвращает активное аудиоустройство.
getEffects()
Возвращает активный эффект предварительной обработки. Обратите внимание, что активный эффект может отличаться от возвращенного методом getClientEffects(), если клиент не является активным приложением с наивысшим приоритетом.
getFormat()
Возвращает свойства потока. Обратите внимание, что аудиоданные, полученные клиентом, всегда соответствуют формату, возвращаемому методом getClientFormat(). Фреймворк автоматически выполняет необходимое преобразование частоты дискретизации, каналов и формата из формата, используемого в аппаратном интерфейсе, в формат, указанный клиентом.
AudioRecord.getActiveRecordingConfiguration()
Возвращает активную конфигурацию записи.

Чтобы получить общие сведения обо всех активных записях на устройстве, вызовите метод AudioManager.getActiveRecordingConfigurations().