Отладка звука

В этой статье описаны некоторые советы и рекомендации по отладке звука Android.

Тройник раковина

«Т-приемник» — это функция отладки AudioFlinger, доступная только в пользовательских сборках и предназначенная для сохранения короткого фрагмента недавнего аудио для последующего анализа. Это позволяет сравнивать то, что было фактически воспроизведено или записано, с тем, что ожидалось.

В целях конфиденциальности тройник по умолчанию отключен как во время компиляции, так и во время выполнения. Чтобы использовать тройник, вам нужно будет включить его путем повторной компиляции, а также путем установки свойства. Обязательно отключите эту функцию после завершения отладки; тройник-приемник не следует оставлять включенным в производственных сборках.

Инструкции в этом разделе предназначены для Android 7.x и выше. Для Android 5.x и 6.x замените /data/misc/audioserver на /data/misc/media . Кроме того, вы должны использовать сборку userdebug или eng. Если вы используете сборку userdebug, отключите verity с помощью:

adb root && adb disable-verity && adb reboot

Настройка во время компиляции

  1. cd frameworks/av/services/audioflinger
  2. Отредактируйте Configuration.h .
  3. Раскомментируйте #define TEE_SINK .
  4. Пересоберите libaudioflinger.so .
  5. adb root
  6. adb remount
  7. Отправьте или синхронизируйте новый libaudioflinger.so с /system/lib устройства.

Настройка во время выполнения

  1. adb shell getprop | grep ro.debuggable
    Убедитесь, что выходные данные: [ro.debuggable]: [1]
  2. adb shell
  3. ls -ld /data/misc/audioserver

    Убедитесь, что результат:

    drwx------ media media ... media
    

    Если каталог не существует, создайте его следующим образом:

    mkdir /data/misc/audioserver
    chown media:media /data/misc/audioserver
    
  4. echo af.tee=# > /data/local.prop
    Где значение af.tee — это число, описанное ниже.
  5. chmod 644 /data/local.prop
  6. reboot

Стоимость недвижимости af.tee

Значение af.tee — это число от 0 до 7, выражающее сумму нескольких битов, по одному на функцию. См. код AudioFlinger::AudioFlinger() в AudioFlinger.cpp для краткого объяснения каждого бита:

  • 1 = вход
  • 2 = выход FastMixer
  • 4 = AudioRecord и AudioTrack для каждой дорожки

Бита для глубокого буфера или обычного микшера пока нет, но вы можете получить аналогичные результаты, используя «4».

Тестирование и сбор данных

  1. Запустите аудиотест.
  2. adb shell dumpsys media.audio_flinger
  3. Найдите в выводе dumpsys строку, подобную этой:
    tee copied to /data/misc/audioserver/20131010101147_2.wav
    Это файл PCM .wav.
  4. Затем adb pull любые интересующие файлы /data/misc/audioserver/*.wav ; Обратите внимание, что имена файлов дампов, специфичных для треков, не отображаются в выводе dumpsys , но все равно сохраняются в /data/misc/audioserver после закрытия трека.
  5. Прежде чем делиться ими с другими, просмотрите файлы дампа на предмет проблем конфиденциальности.

Предложения

Попробуйте эти идеи для получения более полезных результатов:

  • Отключите звуки касания и щелчки клавиш, чтобы уменьшить прерывания результатов теста.
  • Максимизируйте все объемы.
  • Отключите приложения, которые издают звук или записывают с микрофона, если они не представляют интереса для вашего теста.
  • Дампы конкретных треков сохраняются только при закрытии трека; вам может потребоваться принудительно закрыть приложение, чтобы сбросить данные, относящиеся к его треку.
  • Делайте dumpsys сразу после теста; имеется ограниченное количество места для записи.
  • Чтобы не потерять файлы дампа, периодически загружайте их на свой хост. Сохраняется только ограниченное количество файлов дампа; старые дампы удаляются после достижения этого предела.

Восстановить

Как отмечалось выше, функцию тройника не следует оставлять включенной. Восстановите сборку и устройство следующим образом:

  1. Отмените изменения исходного кода в Configuration.h .
  2. Пересоберите libaudioflinger.so .
  3. Отправьте или синхронизируйте восстановленный libaudioflinger.so с /system/lib устройства.
  4. adb shell
  5. rm /data/local.prop
  6. rm /data/misc/audioserver/*.wav
  7. reboot

медиа.лог

Макросы ALOGx

Стандартным API ведения журнала языка Java в Android SDK является android.util.Log .

Соответствующим API языка C в Android NDK является __android_log_print объявленный в <android/log.h> .

В собственной части платформы Android мы предпочитаем макросы с именами ALOGE , ALOGW , ALOGI , ALOGV и т. д. Они объявлены в <utils/Log.h> , и для целей этой статьи мы будем называть их ALOGx .

Все эти API просты в использовании и хорошо понятны, поэтому они широко распространены на платформе Android. В частности, процесс mediaserver , включающий в себя звуковой сервер AudioFlinger, широко использует ALOGx .

Тем не менее, у ALOGx и его аналогов есть некоторые ограничения:

  • Они подвержены «спаму журналов»: буфер журналов является общим ресурсом, поэтому он может легко переполниться из-за несвязанных записей журнала, что приведет к потере информации. Вариант ALOGV по умолчанию отключен во время компиляции. Но, конечно, даже это может привести к спаму в журналах, если оно включено.
  • Базовые системные вызовы ядра могут блокироваться, что может привести к инверсии приоритетов и, как следствие, к нарушениям и неточностям измерений. Это особенно важно для потоков, критичных ко времени, таких как FastMixer и FastCapture .
  • Если определенный журнал отключен для уменьшения спама в журналах, вся информация, которая могла бы быть записана в этом журнале, теряется. Невозможно включить конкретный журнал задним числом, после того как станет ясно, что журнал был бы интересен.

NBLOG, media.log и MediaLogService.

API-интерфейсы NBLOG и связанный с ними процесс media.log и служба MediaLogService вместе образуют новую систему ведения журналов для мультимедиа и специально разработаны для решения вышеуказанных проблем. Мы будем свободно использовать термин «media.log» для обозначения всех трех, но, строго говоря, NBLOG — это API ведения журналов C++, media.log — это имя процесса Linux, а MediaLogService — это служба связывания Android для проверки журналов.

«Временная шкала» media.log представляет собой серию записей журнала, относительный порядок которых сохраняется. По соглашению каждый поток должен использовать свою собственную временную шкалу.

Преимущества

Преимущества системы media.log заключаются в том, что она:

  • Не спамит основной журнал до тех пор, пока он не понадобится.
  • Можно проверить даже в случае сбоя или зависания mediaserver .
  • Неблокируется на временной шкале.
  • Обеспечивает меньше помех для производительности. (Конечно, ни одна форма ведения журнала не является полностью ненавязчивой.)

Архитектура

На диаграмме ниже показана взаимосвязь процесса mediaserver и процесса init до введения media.log :

Архитектура до media.log

Рисунок 1. Архитектура до использования media.log

Примечательные моменты:

  • init разветвляет и запускает mediaserver .
  • init обнаруживает смерть mediaserver и при необходимости повторно разветвляет его.
  • Журналирование ALOGx не отображается.

На диаграмме ниже показаны новые взаимоотношения компонентов после добавления media.log в архитектуру:

Архитектура после media.log

Рисунок 2. Архитектура после media.log

Важные изменения:

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

Где использовать

Начиная с Android 4.4, в AudioFlinger есть только несколько точек журнала, которые используют систему media.log . Хотя новые API не так просты в использовании, как ALOGx , они и не очень сложны. Мы рекомендуем вам изучить новую систему журналирования для тех случаев, когда в ней нет необходимости. В частности, это рекомендуется для потоков AudioFlinger, которые должны выполняться часто, периодически и без блокировки, таких как потоки FastMixer и FastCapture .

Как использовать

Добавить журналы

Во-первых, вам нужно добавить журналы в ваш код.

В потоках FastMixer и FastCapture используйте такой код:

logWriter->log("string");
logWriter->logf("format", parameters);
logWriter->logTimestamp();

Поскольку временная шкала NBLog используется только потоками FastMixer и FastCapture , взаимное исключение не требуется.

В других потоках AudioFlinger используйте mNBLogWriter :

mNBLogWriter->log("string");
mNBLogWriter->logf("format", parameters);
mNBLogWriter->logTimestamp();

Для потоков, отличных от FastMixer и FastCapture , временная шкала NBLog потока может использоваться как самим потоком, так и операциями связывания. NBLog::Writer не обеспечивает никакого неявного взаимного исключения для каждой временной шкалы, поэтому убедитесь, что все журналы происходят в контексте, в котором удерживается мьютекс потока mLock .

После добавления журналов пересоберите AudioFlinger.

Внимание: для каждого потока требуется отдельная временная шкала NBLog::Writer , чтобы обеспечить безопасность потоков, поскольку временные шкалы по своей конструкции исключают мьютексы. Если вы хотите, чтобы несколько потоков использовали одну и ту же временную шкалу, вы можете защитить существующий мьютекс (как описано выше для mLock ). Или вы можете использовать оболочку NBLog::LockedWriter вместо NBLog::Writer . Однако это сводит на нет главное преимущество этого API: его неблокирующее поведение.

Полный API NBLog находится по адресу frameworks/av/include/media/nbaio/NBLog.h .

Включить медиа.лог

media.log отключен по умолчанию. Он активен только тогда, когда свойство ro.test_harness равно 1 . Вы можете включить его:

adb root
adb shell
echo ro.test_harness=1 > /data/local.prop
chmod 644 /data/local.prop
reboot

Соединение теряется при перезагрузке, поэтому:

adb shell
Команда ps media теперь отобразит два процесса:
  • медиа.лог
  • медиасервер

Запишите идентификатор процесса mediaserver на будущее.

Отобразить временные рамки

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

dumpsys media.log

Обратите внимание, что по замыслу временные шкалы независимы, и возможности их объединения не существует.

Восстановление журналов после смерти медиасервера

Теперь попробуйте убить процесс mediaserver : kill -9 # , где # — это идентификатор процесса, который вы указали ранее. В главном logcat вы должны увидеть дамп из media.log , показывающий все журналы, приведшие к сбою.

dumpsys media.log