오디오 디버깅

컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요.

이 문서에서는 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 편집.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.cppAudioFlinger::AudioFlinger() 에 있는 코드를 참조하세요.

  • 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 매크로

Android SDK의 표준 Java 언어 로깅 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 플랫폼 전체에 널리 퍼져 있습니다. 특히 mediaserver 사운드 서버를 포함하는 미디어 서버 프로세스는 ALOGx 광범위하게 사용합니다.

그럼에도 불구하고 ALOGx 와 친구들에게는 몇 가지 제한 사항이 있습니다.

  • "로그 스팸"에 취약합니다. 로그 버퍼는 공유 리소스이므로 관련 없는 로그 항목으로 인해 쉽게 오버플로되어 정보가 누락될 수 있습니다. ALOGV 변형은 기본적으로 컴파일 타임에 비활성화됩니다. 그러나 물론 활성화된 경우에도 스팸 로그가 발생할 수 있습니다.
  • 기본 커널 시스템 호출이 차단되어 우선 순위가 역전되어 결과적으로 측정 장애 및 부정확성이 발생할 수 있습니다. 이는 FastMixerFastCapture 와 같은 시간이 중요한 스레드에서 특히 중요합니다.
  • 로그 스팸을 줄이기 위해 특정 로그를 비활성화하면 해당 로그에 의해 캡처된 모든 정보가 손실됩니다. 로그가 흥미로웠을 것이 분명해진 후에 는 특정 로그를 소급하여 활성화할 수 없습니다.

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 프로세스의 관계를 보여줍니다.

media.log 이전의 아키텍처

그림 1. media.log 이전의 아키텍처

주목할만한 점:

  • init 포크 및 exec mediaserver .
  • initmediaserver 의 죽음을 감지하고 필요에 따라 다시 포크합니다.
  • ALOGx 로깅은 표시되지 않습니다.

아래 다이어그램은 media.log 가 아키텍처에 추가된 후 구성 요소의 새로운 관계를 보여줍니다.

media.log 이후의 아키텍처

그림 2. media.log 이후의 아키텍처

중요한 변경 사항:

  • 클라이언트는 NBLOG API를 사용하여 로그 항목을 구성하고 공유 메모리의 순환 버퍼에 추가합니다.
  • MediaLogService 는 언제든지 순환 버퍼의 내용을 덤프할 수 있습니다.
  • 순환 버퍼는 공유 메모리의 손상으로 인해 MediaLogService 가 충돌하지 않고 손상의 영향을 받지 않는 버퍼를 최대한 많이 덤프할 수 있도록 설계되었습니다.
  • 순환 버퍼는 새 항목을 쓰고 기존 항목을 읽을 때 차단되지 않고 잠금이 없습니다.
  • 순환 버퍼에 쓰거나 읽는 데 커널 시스템 호출이 필요하지 않습니다(선택적 타임스탬프 제외).

사용처

Android 4.4부터 AudioFlinger에는 media.log 시스템을 사용하는 로그 지점이 몇 개 없습니다. 새로운 API가 ALOGx 만큼 사용하기 쉽지는 않지만 그렇다고 아주 어렵지도 않습니다. 꼭 필요한 경우에 대비하여 새로운 로깅 시스템을 학습하는 것이 좋습니다. 특히 FastMixer , FastCapture 쓰레드와 같이 차단 없이 자주, 주기적으로 실행되어야 하는 AudioFlinger 쓰레드에 추천합니다.

사용하는 방법

로그 추가

먼저 코드에 로그를 추가해야 합니다.

FastMixerFastCapture 스레드에서 다음과 같은 코드를 사용합니다.

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

NBLog 타임라인은 FastMixerFastCapture 스레드에서만 사용되므로 상호 배제가 필요하지 않습니다.

다른 AudioFlinger 스레드에서는 mNBLogWriter 사용:

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

FastMixerFastCapture 이외의 스레드의 경우 스레드의 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 명령은 이제 두 가지 프로세스를 표시합니다.
  • 미디어.로그
  • 미디어 서버

나중에 사용할 수 있도록 mediaserver 의 프로세스 ID를 기록해 두십시오.

타임라인 표시

언제든지 수동으로 로그 덤프를 요청할 수 있습니다. 이 명령은 모든 활성 및 최근 타임라인의 로그를 표시한 다음 지웁니다.

dumpsys media.log

설계상 타임라인은 독립적이며 타임라인을 병합할 수 있는 기능이 없습니다.

미디어 서버 종료 후 로그 복구

이제 mediaserver 프로세스를 종료해 보십시오. kill -9 # , 여기서 #은 앞에서 기록해 둔 프로세스 ID입니다. 메인 logcatmedia.log 에서 덤프가 표시되어야 하며, 충돌로 이어지는 모든 로그를 보여줍니다.

dumpsys media.log