정보공간_1

[7기 강북 전소현] 안드로이드 오디오 볼륨 제어 본문

IT 놀이터/Elite Member Tech & Talk

[7기 강북 전소현] 안드로이드 오디오 볼륨 제어

알 수 없는 사용자 2015. 5. 8. 05:39

안녕하세요. 강북멤버십 23-1기 전소현입니다.

이번 게시물에서는 안드로이드의 오디오 볼륨 제어 흐름을 분석해보겠습니다.

[이 게시물은 안드로이드 KitKat(4.4.2)을 기준으로 직접 분석한 내용을 정리한 것입니다.]

 

안드로이드 시스템의 볼륨은 마스터 볼륨, 스트림 볼륨, 트랙 볼륨으로 이루어지고, 각각의 설명은 아래와 같습니다.

안드로이드에서 모든 소리는 오디오 트랙을 통해서 출력되며, 트랙의 최종 볼륨은 아래와 같이 위의 3가지 볼륨을 모두 반영하여 결정됩니다.

 

이 중에서 오디오 서비스와 오디오 정책 서비스에서 제어하는 볼륨은 스트림 볼륨입니다. 마스터 볼륨은 위의 표에서 설명한 것과 같이 한가지 값으로 고정되어 있어 변경이 불가능 하며, 트랙 볼륨은 오디오 트랙을 만드는 애플리케이션에서 AudioTrack API setStereoVolume() 함수를 통해 결정하므로 오디오 시스템에서는 따로 제어하지 않습니다.

 

그럼 이제부터 스트림 볼륨의 제어 흐름에 대해 자세히 알아보겠습니다.

사용자가 스트림 볼륨을 조절할 수 있는 방법은 다양합니다. 가장 대표적인 방법은 소리 설정의 볼륨 설정 화면에서 슬라이더를 움직여 조절하는 방법이며, 이 화면에서 미디어 스트림, 벨소리 스트림, 알람 스트림 등의 볼륨을 조절할 수 있습니다. 또 안드로이드 디바이스의 측면에 있는 하드웨어 물리 키(이하 상하 키)를 통해서도 조절할 수 있습니다.

이런 방법으로 스트림 볼륨을 바꾸면 아래 그림과 같이 오디오 서비스, 오디오 정책 서비스, 그리고 오디오 플링거 서비스가 서로 정보를 주고 받으며 변경된 볼륨을 반영하게 됩니다.

 

오디오 서비스는 어플리케이션에서 요청한 스트림 볼륨 단계 변경 요청을 받아 시스템에 전달하고, 오디오 정책 서비스로 변경 요청을 내려줍니다. 오디오 정책 서비스는 전달된 스트림 볼륨 단계를 가지고 실제 볼륨을 계산하며, 계산된 볼륨을 오디오 플링거 서비스로 전달합니다. 오디오 플링거 서비스는 오디오 정책 서비스에서 전달 받은 스트림 볼륨과 마스터 볼륨, 트랙 볼륨을 합쳐서 최종 볼륨을 계산하고, 이 볼륨을 가지고 오디오 트랙을 합성하여 출력 스트림으로 내보냅니다.

스트림 볼륨 제어의 큰 흐름은 이와 같고, 좀 더 자세히 분석해보겠습니다.

스마트폰의 볼륨 상하 키를 통해 볼륨을 조절할 경우 사용자에게는 변경되는 볼륨의 아이콘과 슬라이더가 포함된 볼륨 패널이 보여집니다. 키 이벤트의 인식을 시작으로 볼륨 패널이 화면에 나타나기까지의 자세한 함수 흐름은 아래와 같습니다. 아래 흐름도와 함께 안드로이드 프레임워크의 해당 소스들을 직접 확인해보면 이해가 더 쉬울 것 같습니다.

           

먼저, 볼륨 상하 키의 입력은 PhoneWindow.java onKeyDown()/onKeyUp() 함수를 통해 판단됩니다. (, 이는 스마트폰의 스크린이 켜져 있을 경우이며 스크린이 꺼져있을 경우 키 입력 이벤트는 PhoneWindowManager.java에서 판단됩니다.) 여기서 볼륨 상하 키의 입력이 판단되면, AudioManager.java AudioService.java로 변경할 오디오 스트림 타입을 전달합니다.

AudioManager.java AudioService.java에서는 전달받은 스트림 타입의 변경 볼륨을 결정합니다. 그리고 그 결과가 VolumePanel.java postVolumeChanged() 함수를 통해 사용자에게 아이콘과 슬라이더가 포함된 볼륨 패널 형태로 보여지게 됩니다.

 

그럼 한가지 상황을 생각해보겠습니다.

아무것도 하지 않을 때 볼륨 상하 키를 조작하면 벨소리 스트림(STREAM_RING)의 볼륨이 변합니다. 그런데 이 때 음악을 재생시킨 뒤 볼륨 상하 키를 조작하면 미디어 스트림(STREAM_MUSIC)의 볼륨이 변합니다. 우리는 어떠한 조작도 하지 않았는데 이렇게 동작하는 것을 보면 마치 안드로이드 오디오 시스템에서 현재 출력중인 스트림 타입을 판단하는 부분이 있는 것 같습니다.

볼륨 상하 키를 이용해 스트림 볼륨을 변경할 경우 안드로이드 오디오 시스템은 AudioService.java getActiveStreamType() 함수를 통해 현재 활성화 되어있는 스트림 타입을 확인한 뒤 STREAM_VOICE_CALL, STREAM_MUSIC, STREAM_RING 등의 우선순위로 볼륨을 조절할 오디오 스트림 타입을 결정합니다. 

 

위 흐름도와 같이 AudioService.java adjustSuggestedStreamVolume() 함수에서 getActiveStreamType() 함수를 호출하고, 여기서 현재 활성화 되어있는 오디오 스트림 타입을 얻습니다. getActiveStreamType() 함수 내의 활성화 되어있는 오디오 스트림 타입의 우선순위는 다음과 같습니다.

                  

STREAM_MUSIC의 우선순위가 STREAM_RING보다 높기 때문에 안드로이드에서 아무것도 하지 않았을 경우 볼륨 상하 키를 누르면 STREAM_RING의 볼륨이 조절되지만 음악을 재생할 경우 볼륨 상하 키를 누르면 자동으로 STREAM_MUSIC의 볼륨이 조절되는 것입니다.

 

이번 게시물의 분석 과정에서는 여러 소스파일들과 함수들이 언급되어 함수 내용을 모두 담지는 못했습니다. 위에서 이야기 했던 것처럼 게시물의 흐름도와 함께 안드로이드 프레임워크의 해당 소스들을 함께 확인해보면 이해가 더 쉬울 것 같습니다.

 

위 내용은 아래 자료를 참고하여 작성하였습니다.

 - 안드로이드 미디어 프레임워크 (김태연 외 4명 공저)