Се­год­ня нас с тобой ждет нас­тоящая экспе­диция вглубь 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 сле­дующий:

  1. Ана­лиз сис­темно­го жур­нала Android, который мож­но получить с помощью коман­ды logcat.
  2. Изу­чение сос­тояний служб Android, све­дения о которых мож­но получить с помощью коман­ды dumpsys.
  3. Изу­чение сос­тояния под­систе­мы ALSA по содер­жимому катало­га /proc/asound и с помощью ути­литы tinymix.
  4. Ана­лиз динами­чес­кой биб­лиоте­ки слоя абс­трак­ции Audio HAL в сре­де Ubuntu с помощью дизас­сем­бле­ра objdump.
  5. Ана­лиз исходных тек­стов опе­раци­онной сис­темы Android.

Осторожно, кирпич!

Вно­ся изме­нения в кон­фигура­цион­ные фай­лы 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
Ус­трой­ство зву­ковой под­систе­мы 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».

Присоединяйся к сообществу «Xakep.ru»!

Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее

  • Подпишись на наc в Telegram!

    Только важные новости и лучшие статьи

    Подписаться

  • Подписаться
    Уведомить о
    0 комментариев
    Межтекстовые Отзывы
    Посмотреть все комментарии