이 도움말에서는 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
컴파일 시간 설정
cd frameworks/av/services/audioflinger
Configuration.h
를 수정합니다.#define TEE_SINK
를 주석 처리 삭제합니다.libaudioflinger.so
를 다시 빌드합니다.adb root
adb remount
- 새
libaudioflinger.so
를 기기의/system/lib
에 푸시하거나 동기화합니다.
런타임 설정
adb shell getprop | grep ro.debuggable
출력이[ro.debuggable]: [1]
인지 확인합니다.adb shell
ls -ld /data/misc/audioserver
출력이 다음과 같은지 확인합니다.
drwx------ media media ... media
디렉터리가 존재하지 않으면 다음과 같이 디렉터리를 만듭니다.
mkdir /data/misc/audioserver
chown media:media /data/misc/audioserver
echo af.tee=# > /data/local.prop
af.tee
값이 아래에 설명된 숫자인 경우입니다.chmod 644 /data/local.prop
reboot
af.tee
속성 값
af.tee
값은 0과 7 사이의 숫자이며, 기능당 하나씩 여러 비트의 합계를 나타냅니다.
비트 각각에 관한 설명은 AudioFlinger.cpp
의 AudioFlinger::AudioFlinger()
에 있는 코드를 참조하세요. 간단히 설명하자면 다음과 같습니다.
- 1 = 입력
- 2 = FastMixer 출력
- 4 = 트랙당 AudioRecord 및 AudioTrack
딥 버퍼나 일반 믹서를 위한 비트는 아직 없지만 '4'를 사용하면 유사한 결과를 얻을 수 있습니다.
데이터 테스트 및 획득
- 오디오 테스트를 실행합니다.
adb shell dumpsys media.audio_flinger
- 다음과 같은
dumpsys
출력의 라인을 찾습니다.tee copied to /data/misc/audioserver/20131010101147_2.wav
이는 PCM .wav 파일입니다. - 그다음 원하는
/data/misc/audioserver/*.wav
파일을adb pull
합니다. 트랙별 덤프 파일 이름은dumpsys
출력에 표시되지 않으나 트랙 폐쇄 시/data/misc/audioserver
에 저장됩니다. - 다른 사람과 공유하기 전에 개인 정보 보호 문제에 관한 덤프 파일을 검토합니다.
추천
더 유용한 결과를 얻으려면 다음 아이디어를 시도해보세요.
- 테스트 출력에서 중단을 줄이려면 터치 소리와 키 클릭을 사용 중지합니다.
- 모든 볼륨을 최대화합니다.
- 마이크를 통해 소리가 나거나 녹음을 하는 앱이 테스트 대상이 아닌 경우 앱을 사용 중지합니다.
- 트랙별 덤프는 트랙이 폐쇄된 경우에만 저장됩니다. 트랙별 데이터를 덤프하려면 앱을 강제 종료해야 할 수도 있습니다.
- 테스트 직후에
dumpsys
를 실행합니다. 사용 가능한 녹음 공간은 제한됩니다. - 덤프 파일이 손실되지 않도록 주기적으로 호스트에 덤프 파일을 업로드합니다. 제한된 수의 덤프 파일만 보존되며 제한에 도달한 기존 덤프는 삭제됩니다.
복원
위에서 설명한 것처럼 티 싱크 기능은 사용 설정하지 않은 상태로 둡니다. 빌드와 기기를 다음과 같이 복원합니다.
- 소스 코드 변경사항을
Configuration.h
로 되돌립니다. libaudioflinger.so
를 다시 빌드합니다.- 복원된
libaudioflinger.so
를 기기의/system/lib
에 푸시하거나 동기화합니다. adb shell
rm /data/local.prop
rm /data/misc/audioserver/*.wav
reboot
media.log
ALOGx 매크로
Android SDK의 표준 자바 언어 로깅 API는 android.util.Log입니다.
이에 상응하는 Android NDK의 C 언어 API는 <android/log.h>
에서 선언된 __android_log_print
입니다.
Android 프레임워크의 네이티브 부분에서는 이름이 ALOGE
, ALOGW
, ALOGI
, ALOGV
등인 매크로가 선호됩니다. 이 매크로는 <utils/Log.h>
에서 선언되며 이 도움말의 목적에 맞게 ALOGx
로 총칭됩니다.
이 API는 모두 사용하기 쉽고 잘 알려져 있기 때문에 Android 플랫폼에서 널리 사용됩니다. 특히 AudioFlinger 사운드 서버를 포함하는 mediaserver
프로세스는 ALOGx
를 폭넓게 사용합니다.
그러나 ALOGx
등의 매크로에는 다음과 같은 제한사항이 있습니다.
-
이러한 매크로는 '로그 스팸'에 취약합니다. 로그 버퍼는 공유 리소스이므로 관련 없는 로그 항목으로 인해 쉽게 오버플로우되면서 정보 누락이 발생할 수 있습니다.
ALOGV
변이는 컴파일 시간에 기본적으로 사용 중지되지만, 사용 설정되더라도 로그 스팸이 당연히 발생될 수 있습니다. -
기본 커널 시스템 호출에서 차단하면서 우선순위 역전이 발생하여 측정 방해 및 부정확한 결과를 초래할 수 있습니다. 이는 시간이 큰 영향을 미치는
FastMixer
및FastCapture
스레드에 특히 중요한 사항입니다. - 로그 스팸을 줄이기 위해 특정 로그를 사용 중지하면 로그에서 캡처할 수도 있었던 모든 정보가 손실됩니다. 특정 로그가 관심 대상이었을 수 있음이 분명해진 후에는 특정 로그를 소급하여 사용 설정할 수 없습니다.
NBLOG, media.log, MediaLogService
NBLOG
API, 관련 media.log
프로세스, MediaLogService
서비스는 미디어의 최신 로깅 시스템을 구성하며 위 문제를 해결하도록 특별히 설계되었습니다. 'media.log'라는 용어는 세 가지를 모두 지칭하는 데 사용되지만, 엄격히 말하면 NBLOG
는 C++ 로깅 API이고 media.log
는 Linux 프로세스 이름이며 MediaLogService
는 로그를 검사하는 Android 바인더 서비스입니다.
media.log
'타임라인'은 상대적인 순서가 보존되는 일련의 로그 항목입니다.
규칙에 따라 각 스레드는 자체 타임라인을 사용해야 합니다.
이점
media.log
시스템의 이점은 다음과 같습니다.
- 필요하기 전까지는 메인 로그를 스팸으로 처리하지 않습니다.
mediaserver
가 비정상 종료되거나 중단될 때에도 검사될 수 있습니다.- 타임라인별 비블로킹입니다.
- 성능에 미치는 영향이 더 적습니다. 물론 전혀 영향을 미치지 않는 로깅 형식은 없습니다.
아키텍처
아래의 다이어그램은 media.log
가 도입되기 전의 mediaserver
프로세스 및 init
프로세스의 관계를 보여줍니다.
중요 사항:
init
는mediaserver
를 포크하고 실행합니다.init
는mediaserver
의 종료를 감지하고 필요한 경우 다시 분기합니다.ALOGx
로깅이 표시되지 않습니다.
아래의 다이어그램은 아키텍처에 media.log
가 추가된 후의 새로운 구성요소 관계를 보여줍니다.
중요 변경사항:
- 클라이언트는
NBLOG
API를 사용하여 로그 항목을 구성하고 공유 메모리의 순환 버퍼에 추가합니다. -
MediaLogService
는 순환 버퍼의 내용을 언제든지 덤프할 수 있습니다. - 순환 버퍼는 공유 메모리의 손상으로 인해
MediaLogService
가 비정상 종료되지 않도록 설계되었으며, 이러한 손상의 영향을 받지 않는 버퍼만큼 덤프할 수 있습니다. - 순환 버퍼는 새로운 항목을 쓰고 기존 항목을 읽을 때 비블로킹이며 잠금이 없습니다.
- 선택사항인 타임스탬프를 제외한 커널 시스템 호출은 순환 버퍼에서의 쓰기 또는 읽기에 필요하지 않습니다.
용도
Android 4.4의 경우 media.log
시스템을 사용하는 AudioFlinger에 로그 포인트가 많지 않습니다. 새 API는 ALOGx
만큼 사용이 쉽지는 않지만, 아주 어렵지도 않습니다.
반드시 필요한 경우에는 새로운 로깅 시스템을 배우는 것이 좋습니다.
FastMixer
및 FastCapture
스레드와 같은 블로킹 없이 정기적으로 자주 실행되어야 하는 AudioFlinger 스레드의 경우에 특히 권장되는 사항입니다.
사용 방법
로그 추가
먼저 코드에 로그를 추가해야 합니다.
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::Writer
대신 NBLog::LockedWriter
래퍼를 사용할 수도 있습니다.
하지만 이 경우 API의 주요 이점인 비블로킹 동작은 유효하지 않습니다.
전체 NBLog
API는 frameworks/av/include/media/nbaio/NBLog.h
에 위치합니다.
media.log 사용 설정
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
에 다음 두 프로세스가 표시됩니다.- media.log
- mediaserver
나중을 위해 mediaserver
의 프로세스 ID를 적어두세요.
타임라인 표시
언제든지 수동으로 로그 덤프를 요청할 수 있습니다. 이 명령어는 모든 활성 및 최근 타임라인의 로그를 표시한 다음 삭제합니다.
dumpsys media.log
설계상 타임라인은 독립적이며 타임라인 병합 기능은 없습니다.
mediaserver 종료 후 로그 복구
앞서 언급한 #가 프로세스 ID인 kill -9 #
을 통해 이제 mediaserver
프로세스 종료를 시도해 보세요. 메인 logcat
의 media.log
에서 덤프가 표시되어 비정상 종료가 발생하는 모든 로그를 확인할 수 있습니다.
dumpsys media.log