Аудиовход обычно осуществляется через встроенный микрофон, внешний микрофон или аудиоинтерфейс, подключенный к устройству. Аудиовход также может поступать из телефонного разговора.
Иногда два или более приложений могут одновременно пытаться «захватить» один и тот же аудиовход. При этом они могут выполнять разные задачи. Например, некоторые приложения, принимающие аудиосигнал, могут «записывать», как простой диктофон, в то время как другие приложения могут «слушать», как Google Ассистент или служба специальных возможностей, реагирующая на голосовые команды.
В любом случае, этим приложениям необходимо получать аудиовход. На этой странице мы используем термин «захват» независимо от того, записывает приложение или просто слушает.
Если два или более приложений хотят одновременно записывать звук, может возникнуть проблема с передачей аудиосигнала из одного источника всем им. На этой странице описывается, как система Android распределяет аудиовход между несколькими приложениями, которые записывают звук.
Поведение до Android 10
До Android 10 входной аудиопоток мог захватываться только одним приложением одновременно. Если какое-либо приложение уже записывало или слушало аудио, ваше приложение могло создать объект AudioRecord , но при вызове метода AudioRecord.startRecording() возвращалась ошибка, и запись не начиналась.
Исключением из этого правила был случай, когда привилегированное приложение (например, Google Ассистент или служба специальных возможностей) имело разрешение android.permission.CAPTURE_AUDIO_HOTWORD и использовало источник звука типа HOTWORD . В этом случае другое приложение могло начать запись. Когда это происходило, привилегированное приложение завершало работу, а новое приложение захватывало входной сигнал.
В Android 9 было добавлено еще одно изменение: аудиовход могли захватывать только приложения, работающие на переднем плане (или использующие службу переднего плана). Когда приложение без службы переднего плана или компонента пользовательского интерфейса переднего плана начинало захват звука, оно продолжало работать, но не получало звука, даже если в тот момент это было единственное приложение, захватывающее звук.
Поведение Android 10
В версиях до Android 10 действовал принцип «кто первый, тот и получает». Как только приложение начинает записывать звук, другие приложения не могут получить доступ к аудиовходу до тех пор, пока приложение, осуществляющее запись звука, не остановится.
В Android 10 используется схема приоритетов, позволяющая переключать входной аудиопоток между работающими приложениями. В большинстве случаев, если новое приложение получает аудиовход, ранее захватывавшее его приложение продолжает работать, но получает тишину. В некоторых случаях система может продолжать передавать звук обоим приложениям. Различные сценарии совместного использования описаны ниже.
Эта схема аналогична тому, как обрабатывается фокусировка звука несколькими приложениями, конкурирующими за использование аудиовыхода. Однако фокусировка звука управляется программными запросами на усиление и снятие фокуса, в то время как описанная здесь схема переключения входов основана на политике приоритезации, которая применяется автоматически всякий раз, когда новое приложение начинает захват звука.
Для целей записи звука Android различает два типа приложений:
- «Обычные» приложения устанавливаются пользователем.
- На устройстве предустановлены «привилегированные» приложения. К ним относятся Google Ассистент и все службы специальных возможностей.
Кроме того, к приложению применяется иной подход, если оно использует источник звука, содержащий конфиденциальную информацию: CAMCORDER или VOICE_COMMUNICATION .
Правила приоритезации использования и совместного доступа к аудиовходу следующие:
- Привилегированные приложения имеют более высокий приоритет, чем обычные приложения.
- Приложения с видимыми элементами интерфейса на переднем плане имеют более высокий приоритет, чем приложения, работающие в фоновом режиме.
- Приложения, записывающие звук из источника, содержащего конфиденциальную информацию, имеют более высокий приоритет, чем приложения, не содержащие такой информации.
- Два обычных приложения никогда не смогут одновременно записывать звук.
- В некоторых ситуациях приложение с привилегиями может передавать аудиовход другому приложению.
- Если два фоновых приложения с одинаковым приоритетом записывают звук, то более высокий приоритет будет у последнего запущенного приложения.
Сценарии совместного использования
Когда два приложения пытаются записать звук, оба могут принимать входной сигнал, или же одно из них может получить тишину.
Существует четыре основных сценария:
- Ассистент + обычное приложение
- Служба доступности + обычное приложение
- Два обычных приложения
- Голосовой звонок + обычное приложение
Ассистент + обычное приложение
Приложение Assistant является привилегированным, поскольку оно предустановлено и имеет роль RoleManager.ROLE_ASSISTANT . Любое другое предустановленное приложение с этой ролью обрабатывается аналогично.
Android распределяет входной аудиосигнал в соответствии со следующими правилами:
Ассистент может принимать аудиосигнал (независимо от того, находится ли он в фоновом или переднем плане), если другое приложение, использующее источник звука, содержащий конфиденциальную информацию, уже не ведет запись.
Приложение принимает аудиосигнал, если только у Ассистента нет видимого элемента пользовательского интерфейса в верхней части экрана.
Обратите внимание, что оба приложения получают звук только тогда, когда Ассистент находится в фоновом режиме, а другое приложение не захватывает звук из источника, содержащего конфиденциальную информацию.
Служба доступности + обычное приложение
Для AccessibilityService требуется строгое декларирование .
Android распределяет входной аудиосигнал в соответствии со следующими правилами:
Если пользовательский интерфейс сервиса находится поверх остальных, то и сервис, и приложение получают аудиовход. Такое поведение обеспечивает функциональность, например, управление голосовым вызовом или записью видео с помощью голосовых команд.
Если сервис не находится в приоритете, то данный случай рассматривается как обычный случай с двумя приложениями, описанный ниже.
Два обычных приложения
Когда два приложения одновременно ведут запись, звук получает только одно приложение, а другое — тишину.
Android распределяет входной аудиосигнал в соответствии со следующими правилами:
- Если ни одно из приложений не затрагивает вопросы конфиденциальности, звук будет приниматься приложением с пользовательским интерфейсом. Если ни одно из приложений не имеет пользовательского интерфейса, звук будет приниматься тем приложением, которое начало запись позже.
- Если одно из приложений затрагивает вопросы конфиденциальности, оно будет получать аудиопоток, а другое приложение — тишину, даже если у него есть пользовательский интерфейс или оно начало вести запись относительно недавно.
- Если оба приложения чувствительны к вопросам конфиденциальности, то приложение, начавшее запись позже, будет получать аудиопоток, а другое — тишину.
Голосовой звонок + обычное приложение
Голосовой вызов считается активным, если режим аудио, возвращаемый функцией AudioManager.getMode() , равен MODE_IN_CALL или MODE_IN_COMMUNICATION .
Android распределяет входной аудиосигнал в соответствии со следующими правилами:
- В звонок всегда поступает аудиосигнал.
- Приложение может записывать звук, если оно поддерживает услуги для людей с ограниченными возможностями .
Приложение может перехватывать голосовые вызовы, если это привилегированное (предустановленное) приложение с разрешением
CAPTURE_AUDIO_OUTPUT.Для захвата восходящего (TX), нисходящего (RX) или обоих каналов голосового вызова приложение должно указать источники звука
MediaRecorder.AudioSource.VOICE_UPLINKилиMediaRecorder.AudioSource.VOICE_DOWNLINKи/или устройствоAudioDeviceInfo.TYPE_TELEPHONY.
Поведение Android 11
Android 11 (уровень API 30) соответствует описанной выше схеме приоритетов Android 10. Он также предоставляет новые методы в AudioRecord , MediaRecorder и AAudioStream , которые позволяют включать и отключать возможность одновременного захвата звука независимо от выбранного сценария использования.
Новые методы следующие:
-
AudioRecord.Builder.setPrivacySensitive() -
AudioRecord.isPrivacySensitive() -
MediaRecorder.setPrivacySensitive() -
MediaRecorder.isPrivacySensitive() -
AAudioStreamBuilder_setPrivacySensitive() -
AAudioStream_isPrivacySensitive()
Если 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() .