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

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

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

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

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

Инструкции в этом разделе предназначены для 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 forks и execs 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 # , где # — идентификатор процесса, который вы указали ранее. Вы должны увидеть дамп из media.log в главном logcat , показывающий все журналы, приведшие к сбою.

dumpsys media.log