Debugowanie dźwięku

W tym artykule znajdziesz kilka porad i wskazówek dotyczących debugowania dźwięku w Androidzie.

Umywalka

„Zlew” to funkcję debugowania AudioFlinger, dostępną tylko w kompilacjach niestandardowych, do zachowania krótkiego fragmentu najnowszego dźwięku do późniejszej analizy. Dzięki temu można porównać to, co zostało rzeczywiście odtworzone lub nagrane. w porównaniu z oczekiwanymi.

Aby zapewnić prywatność, zlew jest domyślnie wyłączony zarówno podczas kompilacji, jak i w czasie wykonywania. Aby użyć umywalki, musisz go włączyć przez ponowną kompilację, a także przez ustawienie właściwości. Pamiętaj, aby wyłączyć tę funkcję po debugowanie; Zlew nie powinien być włączony w konstrukcjach produkcyjnych.

Instrukcje w tej sekcji dotyczą Androida 7.x lub nowszego. Na urządzeniu z Androidem 5.x i 6.x zamień /data/misc/audioserver na /data/misc/media Dodatkowo musisz użyć interfejsu Userdebug lub dla programistów. Jeśli używasz kompilacji debugującej użytkownika, wyłącz weryfikację za pomocą:

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

Konfiguracja podczas kompilacji

  1. cd frameworks/av/services/audioflinger
  2. Edytuj Configuration.h.
  3. Usuń komentarz #define TEE_SINK.
  4. Odbuduj libaudioflinger.so.
  5. adb root
  6. adb remount
  7. Przekaż nowe urządzenie libaudioflinger.so lub zsynchronizuj je z urządzeniem /system/lib.

Konfiguracja środowiska wykonawczego

  1. adb shell getprop | grep ro.debuggable
    Sprawdź, czy dane wyjściowe to: [ro.debuggable]: [1]
  2. adb shell
  3. ls -ld /data/misc/audioserver

    Sprawdź, czy dane wyjściowe:

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

    Jeśli katalog nie istnieje, utwórz go w następujący sposób:

    mkdir /data/misc/audioserver
    chown media:media /data/misc/audioserver
    
  4. echo af.tee=# > /data/local.prop
    Gdzie wartość af.tee jest liczbą opisaną poniżej.
  5. chmod 644 /data/local.prop
  6. reboot

Wartości właściwości af.tee

Wartość af.tee jest liczbą od 0 do 7, która wyraża sumę kilku bitów, po jednym na cechę. Zobacz kod na stronie AudioFlinger::AudioFlinger() w aplikacji AudioFlinger.cpp aby wyjaśnić każdy z nich, ale pokrótce:

  • 1 = dane wejściowe
  • 2 = wynik narzędzia FastMixer
  • 4 = każda ścieżka dźwiękowa i ścieżka audio

Nie ma jeszcze czegoś dla głębokiego bufora ani zwykłego miksera, ale możesz uzyskać podobne wyniki, używając „4”.

Testowanie i pozyskiwanie danych

  1. Przeprowadź test dźwięku.
  2. adb shell dumpsys media.audio_flinger
  3. Poszukaj wiersza w danych wyjściowych dumpsys, na przykład:
    tee copied to /data/misc/audioserver/20131010101147_2.wav
    To jest plik WAV PCM.
  4. Następnie adb pull /data/misc/audioserver/*.wav potrzebnych plików; pamiętaj, że nazwy plików zrzutu specyficznych dla ścieżek nie są widoczne Dane wyjściowe: dumpsys, ale zostaną zapisane w: /data/misc/audioserver po zamknięciu ścieżki.
  5. Zanim udostępnisz pliki zrzutu, sprawdź je pod kątem kwestii związanych z prywatnością.

Sugestie

Aby uzyskać bardziej przydatne wyniki, wypróbuj te pomysły:

  • Wyłącz dźwięki przy dotknięciu i kliknięcia klawiszy, aby ograniczyć zakłócenia w wyniku testu.
  • Maksymalizuj wszystkie woluminy.
  • Wyłącz aplikacje, które odtwarzają dźwięk lub nagrywają dźwięk z mikrofonu. jeśli nie interesuje Pana/Panią test.
  • Zrzuty konkretnego toru są zapisywane tylko wtedy, gdy ścieżka jest zamknięta. może być konieczne wymuszenie zamknięcia aplikacji w celu pobrania danych związanych ze ścieżką
  • dumpsys natychmiast po zakończeniu testu. ilość dostępnego miejsca do nagrywania jest ograniczona.
  • Aby upewnić się, że nie utracisz plików zrzutu, okresowo przesyłaj je na serwer. Zachowana zostanie tylko ograniczona liczba plików zrzutu. starsze zrzuty są usuwane po osiągnięciu tego limitu.

Przywróć

Jak wspomnieliśmy powyżej, funkcja umywalki nie powinna być włączona. Przywróć kompilację i urządzenie w ten sposób:

  1. Cofnij zmiany w kodzie źródłowym na Configuration.h.
  2. Odbuduj libaudioflinger.so.
  3. Przekaż lub zsynchronizuj przywrócone dane libaudioflinger.so z linkiem /system/lib na urządzeniu.
  4. adb shell
  5. rm /data/local.prop
  6. rm /data/misc/audioserver/*.wav
  7. reboot

media.log

Makra ALOGx

Standardowy interfejs API do logowania języka Java w pakiecie Android SDK to android.util.Log.

Odpowiedni interfejs API w języku C w Androidzie NDK to __android_log_print zadeklarowano w dokumencie <android/log.h>.

W ramach natywnej platformy Androida preferuj makra o nazwach ALOGE, ALOGW, ALOGI, ALOGV itp. są zadeklarowane w <utils/Log.h>, a na potrzeby tego artykułu będziemy je razem określać jako ALOGx.

Wszystkie te interfejsy API są łatwe w użyciu i zrozumiałe, więc są wszechobecne na całej platformie Androida. Zwłaszcza mediaserver w tym serwer dźwięku AudioFlinger, korzysta ALOGx dokładnie.

Istnieją jednak pewne ograniczenia dotyczące użytkownika ALOGx i znajomych:

  • Są narażone na „dziennik spamowy”: bufor dziennika jest zasobem współużytkowanym. dlatego może się łatwo pojawić z powodu niepowiązanych wpisów logu, co skutkuje niewykorzystane informacje. Wariant „ALOGV” jest wyłączony na podczas kompilacji. Oczywiście nawet to może doprowadzić do spamu w dziennikach. (jeśli jest włączony).
  • Podstawowe wywołania systemu jądra mogą blokować, co może prowadzić do odwrócenie priorytetu, a w konsekwencji zakłócenia pomiaru, nieścisłości. To z dotyczy szczególnie ważnych wątków, takich jak FastMixer i FastCapture.
  • Jeśli dany dziennik zostanie wyłączony, aby zredukować ilość spamu, wszystkie informacje, które zostałyby zarejestrowane przez ten dziennik, zostaną utracone. Nie można włączyć określonego logu wstecznie, po staje się jasne, że dziennik byłby interesujący.

NBLOG, media.log i MediaLogService

Interfejsy API usługi NBLOG i powiązane z nimi media.log proces i MediaLogService razem tworzą nowszy system rejestrowania multimediów. które mają rozwiązać powyższe problemy. Luźno posługujemy się tym terminem „media.log” w odniesieniu do wszystkich trzech. Mówiąc tylko w skrócie NBLOG, Interfejs API logowania w C++, media.log to nazwa procesu w systemie Linux, a MediaLogService to usługa powiązań Androida służąca do analizowania dzienników.

„Oś czasu” media.log to seria wpisów logu, których względna kolejność jest zachowywana. Zgodnie z konwencją każdy wątek powinien mieć własną oś czasu.

Zalety

Zaletą systemu media.log jest to, że:

  • Nie spamuje głównego dziennika, chyba że jest to potrzebne.
  • Można sprawdzić nawet wtedy, gdy mediaserver ulegnie awarii lub się zawiesza.
  • Nie blokuje treści według osi czasu.
  • Mniejsze zakłócenia działania. (Oczywiście żadna forma rejestrowania nie jest nieuciążliwa).

Architektura

Poniższy diagram przedstawia zależność procesu mediaserver i proces init, przed wprowadzeniem media.log:

Architektura przed media.log

Rysunek 1. Architektura przed media.log

Istotne informacje:

  • init rozwidla i wykonanie mediaserver.
  • init wykrywa śmierć użytkownika mediaserver i w razie potrzeby ponownie otwiera rozwidlenie.
  • Logowanie typu ALOGx nie jest wyświetlane.

Poniższy diagram przedstawia nowe relacje komponentów. po dodaniu do architektury media.log:

Architektura po media.log

Rysunek 2. Architektura po media.log

Ważne zmiany:

  • Klienty używają interfejsu API NBLOG do tworzenia wpisów logu i dołączania ich do zapętlenia w pamięci współdzielonej.
  • MediaLogService może w każdej chwili pobrać zawartość okrągłego bufora.
  • Okrągły bufor został zaprojektowany w taki sposób, że jakiekolwiek uszkodzenie pamięć współdzielona nie ulegnie awarii MediaLogService i nadal będzie mogła aby pobrać jak najwięcej bufora, na które nie wpływa uszkodzenie.
  • Okrągły bufor nie blokuje pisania i nie blokuje go. nowych wpisów i czytanie istniejących.
  • Do zapisu w buforze kołowym ani odczytu z niego nie są wymagane żadne wywołania systemowe jądra (inne niż opcjonalne sygnatury czasowe).

Gdzie można płacić

Od Androida 4.4 w AudioFlinger jest tylko kilka punktów rejestrowania. używający systemu media.log. Chociaż nowe interfejsy API nie są łatwe w obsłudze jako ALOGx, ale też nie są bardzo trudne. Zachęcamy do zapoznania się z nowym systemem rejestrowania danych, gdy jest to niezbędne. Zalecane jest w szczególności w przypadku wątków AudioFlinger, które muszą będą przeprowadzane często, okresowo i bez blokowania reklam, takich jak FastMixer i FastCapture wątków.

Instrukcje korzystania

Dodaj dzienniki

Najpierw musisz dodać do kodu logi.

W wątkach FastMixer i FastCapture użyj takiego kodu:

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

Ponieważ oś czasu NBLog jest używana tylko przez funkcje FastMixer i Wątki: FastCapture, nie ma potrzeby wzajemnego wykluczania.

W innych wątkach AudioFlinger użyj parametru mNBLogWriter:

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

W wątkach innych niż FastMixer i FastCapture Oś czasu NBLog wątku może być używana zarówno przez sam wątek, jak i za pomocą operacji tworzenia powiązań. NBLog::Writer nie oferuje żadnych niejawne wzajemne wykluczanie na osi czasu, upewnij się więc, że wszystkie logi są w kontekście, w którym jest stosowany muteks mLock wątku.

Po dodaniu logów ponownie skompiluj AudioFlinger.

Uwaga: Każdy wątek musi mieć oddzielną oś czasu NBLog::Writer, aby zapewnić bezpieczeństwo wątków, ponieważ osie czasu domyślnie pomijają algorytmy wyciszania. Jeśli chcesz, aby więcej niż 1 wątek korzystał z tej samej osi czasu, możesz chronić go za pomocą tagu istniejący muteks (jak opisano powyżej dla mLock). Możesz też użyj opakowania NBLog::LockedWriter zamiast NBLog::Writer. Neguje to jednak główną zaletę tego interfejsu API: jego nieblokowanie zachowanie użytkownika.

Pełny interfejs API NBLog jest dostępny pod adresem frameworks/av/include/media/nbaio/NBLog.h.

Włącz media.log

Funkcja media.log jest domyślnie wyłączona. Jest aktywne tylko wtedy, gdy usługa Obecny stan „ro.test_harness”: 1. Możesz włączyć ten tryb:

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

Podczas ponownego uruchamiania tracisz połączenie, więc:

adb shell
Polecenie ps media pokaże teraz 2 procesy:
  • media.log
  • serwer mediów

Zapisz identyfikator procesu mediaserver na później.

Wyświetl oś czasu

W każdej chwili możesz ręcznie poprosić o zrzut dziennika. To polecenie wyświetla logi ze wszystkich aktywnych i ostatnich osi czasu, a następnie je usuwa:

dumpsys media.log

Pamiętaj, że ramy czasowe są niezależne od siebie, i nie ma możliwości scalenia ram czasowych.

Odzyskaj dzienniki po śmierci serwera mediów

Teraz spróbuj wyłączyć proces mediaserver: kill -9 #, gdzie # to identyfikator procesu zanotowany wcześniej. Powinien pojawić się zrzut z usługi media.log w głównej aplikacji logcat, pokazując wszystkie logi prowadzące do awarii.

dumpsys media.log