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
cd frameworks/av/services/audioflinger
- Edytuj
Configuration.h
. - Usuń komentarz
#define TEE_SINK
. - Odbuduj
libaudioflinger.so
. adb root
adb remount
- Przekaż nowe urządzenie
libaudioflinger.so
lub zsynchronizuj je z urządzeniem/system/lib
.
Konfiguracja środowiska wykonawczego
adb shell getprop | grep ro.debuggable
Sprawdź, czy dane wyjściowe to:[ro.debuggable]: [1]
adb shell
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
echo af.tee=# > /data/local.prop
Gdzie wartośćaf.tee
jest liczbą opisaną poniżej.chmod 644 /data/local.prop
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
- Przeprowadź test dźwięku.
adb shell dumpsys media.audio_flinger
- Poszukaj wiersza w danych wyjściowych
dumpsys
, na przykład:
tee copied to /data/misc/audioserver/20131010101147_2.wav
To jest plik WAV PCM. - 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. - 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:
- Cofnij zmiany w kodzie źródłowym na
Configuration.h
. - Odbuduj
libaudioflinger.so
. - Przekaż lub zsynchronizuj przywrócone dane
libaudioflinger.so
z linkiem/system/lib
na urządzeniu. adb shell
rm /data/local.prop
rm /data/misc/audioserver/*.wav
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
iFastCapture
. - 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
:
Istotne informacje:
init
rozwidla i wykonaniemediaserver
.init
wykrywa śmierć użytkownikamediaserver
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
:
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 shellPolecenie
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