Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
Сегодня нас с тобой ждет настоящая экспедиция вглубь Android. Нашей сиюминутной целью будет устранить баг воспроизведения звука на телеприставке X96Q PRO. На пути к этой цели мы подробно изучим все части звуковой системы и научимся вносить изменения в низкоуровневые настройки, недоступные из графического интерфейса.
Android в нашей подопытной приставке точно такой же, как в телефонах и автомагнитолах. Все принципиальные сведения, кроме конкретных схем и конкретного кода библиотеки HAL, актуальны для всех устройств на Android 10, и, с большой долей вероятности, от Android 7 до Android 13 включительно. Начиная с версии 14 в Android стали использовать язык описания интерфейса AIDL вместо HIDL, но это касается в большей степени низкоуровневых разработчиков.
Эта история началась с замены телевизионной приставки. У меня был старенький девайс с одним гигабайтом памяти — на смену ему я выбрал модель X96Q PRO в варианте с двумя гигабайтами оперативки. Ее операционная система Android 10 не захламлена, в ней разблокирована возможность получения прав суперпользователя. Кажется, то что надо.
Заполучив приставку, я ее подключил, настроил и поставил на нее привычный набор приложений. На первый взгляд все было прекрасно: видео воспроизводилась, музыка звучала, игры игрались.
Но уже на второй день я почувствовал неладное. Какой бы медиаконтент ни играл, в звуковом сопровождении постоянно проскакивали то ли пощелкивания, то ли потрескивания, как будто во время просмотра аналогового телевидения рядом проходит грозовой фронт.
В художественных фильмах или новостных программах это почти незаметно, но в отдельных музыкальных композициях звук искажался до невозможности. Я не аудиофил и меня не испугать записью концерта в MP3 со скоростью потока 128 Кбит/с. Но щелчки все же стали действовать на нервы. Я понял, что если это не исправить, то скоро начнет дергаться глаз.
Если у тебя есть устройство с Android, ты можешь прямо сейчас проверить, присущ ли ему описываемый дефект. Для этого воспроизведи файл 1TR110-1_Kap8.1_Waehlton.ogg с записью гудка европейской телефонной станции (это синусоида с частотой 425 Гц). На качественном устройстве тон должен быть чистым, мягким и ровным. Если же звук плавает, в нем слышны посторонние шумы или потрескивания, то сочувствую: твое устройство подвержено проблеме, которую мы будем решать в этой статье.
Возможно, тебя миновала эта неприятность, но тебе интересно устройство аудиоподсистемы Android 10 и способ изменения частоты дискретизации выводимого приставкой аудиопотока. Об этом я тоже постараюсь рассказать.
Сначала, как любой нормальный человек, я попытался настроить звук через интерфейс Android, но выбор там невелик: всего‑то и можно, что включить или выключить AUDIO_CODEC
, AUDIO_HDMI
и режим проброса звука passthrough. Вне зависимости от установленных флажков, дефекты звука продолжали свое деструктивное воздействие на психику.
Я перебрал несколько медиапроигрывателей, но это тоже не дало результата. Вот и все, обычный пользователь потерпел поражение в этой схватке с Android. Поэтому на сцену пришлось выйти инженеру. Инженерный подход к решению проблем подразумевает сбор и изучение доступной информации об объекте, его диагностику для выяснения причин проблемы, выбор решения и исправление ситуации. Что ж, приступим!
План исследования звуковой подсистемы Android следующий:
logcat
. dumpsys
. /proc/asound
и с помощью утилиты tinymix. Осторожно, кирпич!
Внося изменения в конфигурационные файлы Android-устройства, оказалось удивительно легко привести его в неработоспособное состояние, или, как говорят, «окирпичить». Например, если в теге HDMI Out файла audio_policy_configuration.xml
слово Out написать с маленькой буквы, загрузка телевизионной приставки будет останавливаться на этапе демонстрации анимированной заставки.
В большинстве случаев восстановление работоспособности возможно, но для этого потребуются специальные знания и софт. С последним сложнее всего. На страничке приставки X96Q PRO есть четыре варианта firmware, но только один подходит к моему экземпляру. Попытка «прошить» другие приводит к тому, что устройство перестает опознаваться даже сервисным ПО.
Поэтому трезво оцени свои силы перед тем, как что‑то сделать на реальном оборудовании. Как минимум заранее ознакомься с опытом неудачников на тематических форумах. Но все равно будь готов к тому, что устройство может быть безнадежно испорчено.
Команды можно выполнять непосредственно в консоли устройства из приложения‑терминала, например, Terminal Emulator for Android. Но я использовал возможности удаленной отладки устройств с Android, для чего установил на свой компьютер пакет SDK Platform Tools с утилитой командной строки adb.
Для замены конфигов и установки утилиты tinymix я использовал приложение Magisk, которое дает права суперпользователя и позволяет оформлять модификации в виде подключаемых модулей.
Хоть приставка и была изначально рутована, в использовании Magisk нашлось неоспоримое преимущество. Если с новым вариантом конфига приставка не загружается, достаточно дважды перезагрузить ее, переподключая блок питания. Magisk подсчитывает количество неудачных включений и на третий раз отключает все установленные модули, что позволяет приставке загрузиться в заводском исполнении.
info
Иногда Magisk приводит к интересным побочным эффектам. Я заметил, что при активном модуле с исправлениями после перезагрузки восстанавливается расположение плиток на рабочем столе ATV Launcher. Чтобы переместить плитки «навсегда», надо сначала отключить модуль, потом выполнить перемещения, после чего снова его включить. Такая защита от случайного нарушения привычной раскладки интерфейса мне показалась очень удобной.
Что такое цифровой звук
Чтобы лучше понимать работу звуковой подсистемы приставки, надо вспомнить, что собой представляют звуковые данные. Как ты знаешь из школьного курса физики, человек слышит звук из‑за изменения давления воздуха на расположенную в ухе барабанную перепонку с частотой 20 — 20000 Гц. Этот процесс, как и все остальные физические процессы в макромире, благодаря явлению инерции является плавным и непрерывным.
Для использования в компьютерной технике аналоговая физическая величина — в данном случае давление воздуха — представляется конечной последовательностью чисел из ограниченного набора с помощью двух подходов: дискретизации по времени и квантования по уровню.
Оцифровка звука происходит путем дискретизации по времени и квантования по уровню
Суть дискретизации состоит в записи значений физической величины не непрерывно, а только в определенные моменты времени, следующие с определенной частотой. Выбор частоты дискретизации определяется теоремой отсчетов (Котельникова — Найквиста — Шеннона), которая гласит, что исходный сигнал, максимальная частота компонентов которого не превышает F, можно полностью восстановить по измеренным отсчетам, следующим с частотой не меньше 2 × F. Таким образом, по отсчетам с частотой дискретизации 44100 Гц можно восстановить сигнал, частота компонентов которого не превышает 22050 Гц, что перекрывает указанный выше диапазон звуков, слышимых человеком.
Впрочем, точное восстановление сигнала возможно лишь в том случае, если измеренные значения записаны без ошибок. Однако аналого‑цифровые преобразователи (АЦП) отображают измеренную датчиком физическую величину на конечную разрядную сетку машинного представления числа, выполняя квантование значения по уровню. Это неизбежно ведет к ошибкам (погрешностям) записи измеренных значений. Например, 16-разрядные АЦП непрерывный интервал изменения физической величины отображают на 216 = 65536 уровней, которые могут быть пронумерованы целыми числами из диапазона -32768…+32767.
Описанный способ записи аналогового сигнала в цифровой форме называется импульсно‑кодовой модуляцией PCM (Pulse-Code Modulation). Для увеличения компактности записей используются разные методы их сжатия: с потерями (AAC, MP3, OGG) или без потерь (FLAC, WMA Losseless). Но перед воспроизведением данные все равно потребуется распаковать в импульсно‑кодовую форму, которая пригодна для непосредственного преобразования в физическую величину — звук.
В Android запросы на работу со звуком обслуживает служба Audio Flinger сервера звука, которая через слой абстракции от аппаратуры HAL (Hardware Abstraction Layer) управляет звуковой подсистемой ALSA (Advanced Linux Sound System) уровня ядра.
Приложения для воспроизведения звука в Android используют объект класса android.media.AudioTrack, с помощью которого данные в кодировке PCM из программного буфера направляются в устройство воспроизведения. Служба Audio Flinger тесно взаимодействует со службой Audio Policy, которая на основе конфига audio_policy_configuration.xml
определяет, какие устройства и в каком режиме должны использоваться для воспроизведения звука.
Устройство звуковой подсистемы Android
Слой аппаратной абстракции (HAL) сопоставляет стандартные виртуальные устройства Android — такие как AUDIO_DEVICE_OUT_SPEAKER
(встроенный динамик), AUDIO_DEVICE_OUT_WIRED_HEADPHONE
(проводные наушники) и AUDIO_DEVICE_OUT_AUX_DIGITAL
(цифровой аудиовыход) — с конкретным физическим оборудованием. Это оборудование определяется и настраивается на уровне ядра Linux через описание в дереве устройств (Device Tree).
Разработчики HAL перечисляют устройства, которые могут использоваться аудиосервером, в секции <devicePorts>
файла audio_policy_configuration.xml
, например:
<devicePorts> <devicePort tagName="Speaker" type="AUDIO_DEVICE_OUT_SPEAKER" role="sink"></devicePort> <devicePort tagName="HDMI Out" type="AUDIO_DEVICE_OUT_AUX_DIGITAL" role="sink"></devicePort></devicePorts>
В приведенном примере виртуальному устройству AUDIO_DEVICE_OUT_SPEAKER
, которое играет роль приемника звука sink (в противоположность источникам звука — source), назначается имя Speaker. По этому имени на устройство ссылаются в других местах конфига. Например, при перечислении аудиоустройств, которые встроены в приставку (в противоположность устройствам, которые могут подключаться периодически):
<attachedDevices> <item>Speaker</item></attachedDevices>
Анализировать работу звуковой подсистемы Android на уровне аудиосервера помогает информация о состоянии служб, которую выводит команда dumpsys. В нашем случае полезны два варианта этой команды:
dumpsys media.audio_policy dumpsys media.audio_flinger
Первая команда рассказывает о том, как были интерпретированы настройки из audio_policy_configuration.xml
. В частности, какой именно конфиг используется:
Config source: /vendor/etc/audio_policy_configuration.xml
Далее dumpsys в понятной форме отображает правила, взятые из конфига. Например, сведения об устройствах и приоритетном канале воспроизведения звука описываются так:
<modules> <module name="primary" halVersion="2.0"> <attachedDevices> <item>Speaker</item> ... </attachedDevices> <defaultOutputDevice>Speaker</defaultOutputDevice> <mixPorts> <mixPort name="primary output" role="source" flags="AUDIO_OUTPUT_FLAG_PRIMARY"> <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/> </mixPort> ... </mixPorts> <devicePorts> <devicePort tagName="Speaker" type="AUDIO_DEVICE_OUT_SPEAKER" role="sink"></devicePort> <devicePort tagName="HDMI Out" type="AUDIO_DEVICE_OUT_AUX_DIGITAL" role="sink"></devicePort> ... </devicePorts> <routes> <route type="mix" sink="Speaker" sources="primary output"/> <route type="mix" sink="HDMI Out" sources="primary output"/> ... </routes> </module></modules>
А вот расшифровка:
- Available output devices: Device 1: - id: 2 - tag name: Speaker - type: AUDIO_DEVICE_OUT_SPEAKER - Profiles: Profile 0:[dynamic format][dynamic channels][dynamic rates] ... HW Modules dump: - HW Module 1: - name: primary - handle: 10 - version: 2.0 - outputs: output 0: - name: primary output - Profiles: Profile 0: - format: AUDIO_FORMAT_PCM_16_BIT - sampling rates:48000 - channel masks:0x0003 - flags: 0x0002 (AUDIO_OUTPUT_FLAG_PRIMARY) - Supported devices: Device 1: - id: 2 - tag name: Speaker - type: AUDIO_DEVICE_OUT_SPEAKER ... Device 7: - tag name: HDMI Out - type: AUDIO_DEVICE_OUT_AUX_DIGITAL|AUDIO_DEVICE_OUT_HDMI
Порты микшера mixPort описывают разные технологии обработки звуковых данных, которые определяются комбинацией значений в атрибуте flags
. Например, в настройках обязательно должен присутствовать единственный приоритетный порт микшера с флагом AUDIO_OUTPUT_FLAG_PRIMARY
. Другие варианты портов: AUDIO_OUTPUT_FLAG_DEEP_BUFFER
— использование «глубокого» буфера для аудиопотоков, допускающих задержку воспроизведения, AUDIO_OUTPUT_FLAG_DIRECT
— направление данных непосредственно на устройство воспроизведения, AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD
— обработка упакованных данных (MP3, AAC и других) с помощью аппаратного декодера.
Связи портов микшера с устройствами воспроизведения звука описываются в секции маршрутов <routes>
. Для каждого устройства‑приемника sink может быть указано через запятую несколько портов‑источников звука sources.
Источник: xakep.ru