More Related Content Similar to Android audio system(audioflinger) (20) Android audio system(audioflinger)2. 1.Audio system 전체 구조 안드로이드의 모든것 분석과 포팅 정리
Application Media player App Media Recorder App Volume /mode change
Application
Framework
Native
Framework
HAL
Kernel
2
3. 1.Audio HAL의 초기화 안드로이드의 모든것 분석과 포팅 정리
Init.rc
service media /system/bin/mediaserver
user media
group system audio camera graphics inet net_bt net_bt_admin net_raw sdcard_rw
Main_mediaserver.cpp
int main(int argc, char** argv)
{
AudioFlinger::instantiate();
AudioPolicyService::instantiate();
}
AudioFlinger.h
class AudioFlinger :
public BinderService<AudioFlinger>,
public BnAudioFlinger
{
friend class BinderService<AudioFlinger>;
public:
…
3
4. 1.Audio HAL의 초기화 안드로이드의 모든것 분석과 포팅 정리
BinderService.h
class BinderService
{
public:
static status_t publish() {
sp<IServiceManager> sm(defaultServiceManager());
return sm->addService(String16(SERVICE::getServiceName()), new SERVICE());
}
static void instantiate() { publish(); }
}
AudioFlinger.cpp
AudioFlinger::AudioFlinger()
: BnAudioFlinger(),
mAudioHardware(0), mFmEnabled(false), mMasterVolume(1.0f), mMasterMute(false), mNextUniqueId(1)
{
AudioHardwareInterface* mAudioHardware = AudioHardwareInterface::create();
…
}
4
5. 1.Audio HAL의 초기화 안드로이드의 모든것 분석과 포팅 정리
AudioHardwareinterface.cpp Audioflinger/android.mk
AudioHardwareInterface* AudioHardwareInterface::create() ifeq ($(strip $(BOARD_USES_GENERIC_AUDIO)),true)
{ LOCAL_CFLAGS += -DGENERIC_AUDIO
#ifdef GENERIC_AUDIO
hw = new AudioHardwareGeneric();
#else
// if running in emulation - use the emulator driver BoardConfig.mk
if (property_get("ro.kernel.qemu", value, 0)) { # MultiMedia defines
hw = new AudioHardwareGeneric(); BOARD_USES_GENERIC_AUDIO := false
} BOARD_USES_ALSA_AUDIO := true
else { BUILD_WITH_ALSA_UTILS := true
hw = createAudioHardware(); BOARD_USES_TI_CAMERA_HAL := true
} CAMERA_YUV_FAST_CONVERT := true
Android.mk(AudioFlinger)
AudioHardwareALSA.cpp
android::AudioHardwareInterface *createAudioHardware(void) {
return android::AudioHardwareALSA::create(); libAudio libaudioPolicy
}
AudioHardwareALSA.cpp AudioPolicyManagerALSA.cpp
AudioStreamOutALSA.cpp + libaudiopolicybase
AudioStreamInALSA.cpp (AudioPolicyManagerBase.cpp)
AudioHardwareInterface *AudioHardwareALSA::create() { ALSAStreamOps.cpp
return new AudioHardwareALSA(); ALSAMixer.cpp
} ALSAControl.cpp
+ libaudiointerface
(AudioHardwareInterface.cpp)
5
6. 1.Audio HAL의 초기화 안드로이드의 모든것 분석과 포팅 정리
AudioHardwareALSA::AudioHardwareALSA() :
mALSADevice(0),
mTtyMode(TTY_OFF),
mAcousticDevice(0) “alsa”
{
int err = hw_get_module(ALSA_HARDWARE_MODULE_ID,
(hw_module_t const**)&module);
..
}
int hw_get_module(const char *id, const struct hw_module_t **module)
{
for (i=0 ; i<HAL_VARIANT_KEYS_COUNT+1 ; i++) {
if (i < HAL_VARIANT_KEYS_COUNT) {
if (property_get(variant_keys[i], prop, NULL) == 0) { --------------(1)
continue; “/system/lib/hw”
}
snprintf(path, sizeof(path), "%s/%s.%s.so“,HAL_LIBRARY_PATH1, id, prop); ---------------(2)
if (access(path, R_OK) == 0) break;
“/vendor/lib/hw”
snprintf(path, sizeof(path), "%s/%s.%s.so“,HAL_LIBRARY_PATH2, id, prop); ---------------(3)
if (access(path, R_OK) == 0) break;
} else {
snprintf(path, sizeof(path), "%s/%s.default.so“,HAL_LIBRARY_PATH1, id); ---------------(4)
if (access(path, R_OK) == 0) break;
}
}
if (i < HAL_VARIANT_KEYS_COUNT+1) {
status = load(id, path, module); ---------------(5)
}
6
7. 1.Audio HAL의 초기화 안드로이드의 모든것 분석과 포팅 정리
if (property_get(variant_keys[i], prop, NULL) == 0) { --------------(1)
continue;
variant_keys property value들을 읽어온다.
static const char *variant_keys[] = {
"ro.hardware", 제조회사 ex)HTC
"ro.product.board", board명 ex) H
"ro.board.platform", omap3
"ro.arch“ ””
};
snprintf(path, sizeof(path), "%s/%s.%s.so“,HAL_LIBRARY_PATH1, id, prop); ---------------(2)
if (access(path, R_OK) == 0) break;
/system/lib/hw/alsa.omap3.so가 있는지 찾는다.
Target 모델의 경우 /system/lib/hw의 so file들은 아래와 같다.
acoustics.default.so
alsa.omap3.so
gps.omap3.so
gralloc.default.so
gralloc.omap3.so
lights.omap3.so
overlay.omap3.so
sensors.omap3.so
따라서, path가 alsa.omap3.so 일 경우 break된다.
7
8. 1.Audio HAL의 초기화 안드로이드의 모든것 분석과 포팅 정리
snprintf(path, sizeof(path), "%s/%s.%s.so“,HAL_LIBRARY_PATH2, id, prop); ---------------(3)
if (access(path, R_OK) == 0) break;
/vendor/lib/hw 에 있는 so file들을 찾는다.
snprintf(path, sizeof(path), "%s/%s.default.so“,HAL_LIBRARY_PATH1, id); ---------------(4)
if (access(path, R_OK) == 0) break;
so file을 찾는데 실패 할 경우에는 alsa.default.so 를 load한다.
if (i < HAL_VARIANT_KEYS_COUNT+1) {
status = load(id, path, module); ---------------(5)
}
alsa.omap3.so를 load한다.
static int load(const char *id,const char *path, const struct hw_module_t **pHmi)
{
handle = dlopen(path, RTLD_NOW); -------------------------(1-1)
const char *sym = HAL_MODULE_INFO_SYM_AS_STR;
hmi = (struct hw_module_t *)dlsym(handle, sym);------------(2-1)
}
handle = dlopen(path, RTLD_NOW); -------------------------(1-1)
/system/lib/hw/alsa.omap3.so 를 open한다.
8
9. 1.Audio HAL의 초기화 안드로이드의 모든것 분석과 포팅 정리
hmi = (struct hw_module_t *)dlsym(handle, sym);------------(2-1)
alsa_omap3.cpp의 HAL_MODULE_INFO_SYM 구조체를 hmi로 가져온다.
Alsa_omap3.cpp
extern "C" const hw_module_t HAL_MODULE_INFO_SYM = {
tag : HARDWARE_MODULE_TAG,
version_major : 1,
static hw_module_methods_t s_module_methods = {
version_minor : 0,
open : s_device_open
id : ALSA_HARDWARE_MODULE_ID,
};
name : "Omap3 ALSA module",
author : "Texas Instruments",
methods : &s_module_methods,
dso : 0,
reserved : {0,},
};
AudioHardwareALSA::AudioHardwareALSA() :
mALSADevice(0),
mTtyMode(TTY_OFF),
mAcousticDevice(0)
{
int err = hw_get_module(ALSA_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
module 은 HAL_MODULE_INFO_SYM 를 가리킨다.
err = module->methods->open(module, ALSA_HARDWARE_NAME, &device);-------------------(3-1)
HAL_MODULE_INFO_SYM -> methods ->open 즉, s_device_open을 가리킴.
if (err == 0) {
mALSADevice = (alsa_device_t *)device;
mALSADevice->init(mALSADevice, mDeviceList);
mALSADevice->init 은 alsa_htc.cpp에 있는 s_init을 호출 함.
}
9
10. 1.Audio HAL의 초기화 안드로이드의 모든것 분석과 포팅 정리
static int s_device_open(const hw_module_t* module, const char* name,hw_device_t** device)----(3-2)
{
…
dev->common.close = s_device_close;
dev->init = s_init;
dev->open = s_open;
dev->close = s_close;
dev->standby = s_standby;
dev->route = s_route;
*device = &dev->common;
}
AudioHardwareinterface.cpp
AudioHardwareInterface* AudioHardwareInterface::create()
{ AudioHardwareALSA.cpp
hw = createAudioHardware(); status_t AudioHardwareALSA::initCheck()
hw는 AudioHardwareALSA 를 나타냄. {
if (mALSADevice && mMixer && mMixer->isValid())
if (hw->initCheck() != NO_ERROR) { return NO_ERROR;
hw = new AudioHardwareStub(); else
return NO_INIT;
} }
}
10
11. 2.AudioFlinger class 구조 안드로이드의 모든것 분석과 포팅 정리
BnAudioFlinger
AudioFlinger
Thread
ThreadBase
AudioBufferProvider
TrackBase
BnAudioTrack AudioBufferProvider
playbackThread
BnAudioRecord
Track TrackHandle
RecordThread
outputTrack
RecordTrack RecordHandle
MixerThread DirectoutputThread
DuplicatingThread
11
12. 3.IAudioFlinger 인터페이스 안드로이드의 모든것 분석과 포팅 정리
IInterface
IAudioFlinger
BnAudioFlinger BpAudioFlinger
virtual sp<IAudioTrack> createTrack,
virtual sp<IAudioRecord> openRecord,
AudioFlinger virtual int openOutput,
setMasterVolume,
setMicMute
…
12
13. 4.PlaybackThread(MixerThread)의 생성 안드로이드의 모든것 분석과 포팅 정리
Main_mediaserver.cpp
int main(int argc, char** argv)
{
AudioFlinger::instantiate();
AudioPolicyService::instantiate();
}
AudioPolicyService.cpp
void AudioPolicyService::instantiate() {
defaultServiceManager()->addService(
String16("media.audio_policy"), new AudioPolicyService());
}
AudioPolicyService.cpp
AudioPolicyService::AudioPolicyService()
: BnAudioPolicyService() , mpPolicyManager(NULL)
{
….
mpPolicyManager = createAudioPolicyManager(this);
}
AudioPolicyManagerALSA.cpp
extern "C" AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface)
{
return new AudioPolicyManagerALSA(clientInterface);
}
13
14. 4.PlaybackThread(MixerThread)의 생성 안드로이드의 모든것 분석과 포팅 정리
AudioPolicyManagerALSA 생성자 호출
AudioPolicyManagerALSA::AudioPolicyManagerALSA(AudioPolicyClientInterface *clientInterface)
: AudioPolicyManagerBase(clientInterface)
{
}
AudioPolicyManagerALSA 는 AudioPolicyManagerBase로 부터 상속 받기 때문에
AudioPolicyManagerBase의 생성자를 호출한다.
AudioPolicyManagerBase::AudioPolicyManagerBase(AudioPolicyClientInterface *clientInterface)
{
mpClientInterface = clientInterface;
mAvailableOutputDevices = AudioSystem::DEVICE_OUT_EARPIECE | AudioSystem::DEVICE_OUT_SPEAKER;
mAvailableInputDevices = AudioSystem::DEVICE_IN_BUILTIN_MIC;
mHardwareOutput = mpClientInterface->openOutput(&outputDesc->mDevice,
&outputDesc->mSamplingRate,
&outputDesc->mFormat,
&outputDesc->mChannels,
&outputDesc->mLatency,
outputDesc->mFlags);
}
mpClientInterface는 AudioPolicyService를 나타냄으로
AuidoPolicyService.cpp의 openOutput method를 호출한다.
14
15. 4.PlaybackThread(MixerThread)의 생성 안드로이드의 모든것 분석과 포팅 정리
AuidoPolicyService.cpp
audio_io_handle_t AudioPolicyService::openOutput(…)
{
{
sp<IAudioFlinger> af = AudioSystem::get_audio_flinger(); af는 BpAudioFlinger를 가리킨다.
return af->openOutput(pDevices,
pSamplingRate,
(uint32_t *)pFormat,
pChannels,
pLatencyMs,
flags);
}
AudioFlinger.cpp
int AudioFlinger::openOutput(…)
{
…
AudioStreamOut *output = mAudioHardware->openOutputStream(*pDevices,
(int *)&format,
&channels,
&samplingRate,
&status);
mAudioHardware 는 AudioHardwareALSA 를 가리킨다.
AudioHardwareALSA::openOutputStream는 alsa_omap3.cpp 에 있는 s_open을 호출해서 PCM device를 open하고
HAL의 데이터 출력 Class인 AudioStreamOutALSA를 생성한다.
int id = nextUniqueId(); unique한 id를 생성하고
thread = new MixerThread(this, output, id, *pDevices); 그 id로 MixerThread를 생성한다.
..
}
15
16. 4.PlaybackThread(MixerThread)의 생성 안드로이드의 모든것 분석과 포팅 정리
AudioFlinger::MixerThread::MixerThread(…)
: PlaybackThread(audioFlinger, output, id, device),
mAudioMixer(0)
{
mType = PlaybackThread::MIXER;
mAudioMixer = new AudioMixer(mFrameCount, mSampleRate); AudioMixer class 생성
}
PlaybackThread 생성자 호출
AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id,
uint32_t device)
: ThreadBase(audioFlinger, id), …
ThreadBase생성자 호출
AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, int id)
: Thread(false),
mAudioFlinger(audioFlinger), mSampleRate(0), mFrameCount(0), mChannelCount(0),
mFrameSize(1), mFormat(0), mStandby(false), mId(id), mExiting(false)
{
}
MixerThread id를 mid에 저장한다.
16
17. 4.PlaybackThread(MixerThread)의 생성 안드로이드의 모든것 분석과 포팅 정리
AudioFlinger.cpp
int AudioFlinger::openOutput(…) DefaultKeyedVector< int, sp<PlaybackThread> > mPlaybackThreads;
{
…
mPlaybackThreads.add(id, thread);
생성된 MixerThread를 mPlaybackThreads 에 추가한다.
return id;
MixerThread id를 return한다.
}
AudioFlinger
Threadbase
playbackThread
MixerThread
AudioHardwareInterface
AudioStreamOutALSA
17
18. 5.RecordThread의 생성 안드로이드의 모든것 분석과 포팅 정리
Soundrecorder.java MediaPlayerService.cpp
mRecorder = new Recorder(); sp<IMediaRecorder>
mRecorder.startRecording MediaPlayerService::createMediaRecorder(pid_t pid)
{
sp<MediaRecorderClient> recorder =
new MediaRecorderClient(this, pid);
Recorder.java
}
public void startRecording{
..
mRecorder = new MediaRecorder();
mRecorder.start();
MediaRecorderClient::MediaRecorderClient(…)
{
MediaRecorder.java
mRecorder = new StagefrightRecorder;
public class MediaRecorder{
}
native_setup(new WeakReference<MediaRecorder>(this));
}
JNI
Android_media_MediaRecorder.cpp
static void
StagefrightRecorder::StagefrightRecorder()
android_media_MediaRecorder_native_setup{
: mWriter(NULL),
sp<MediaRecorder> mr = new MediaRecorder();
mOutputFd(-1) {
}
LOGV("Constructor");
reset();
MediaRecorder.cpp
}
MediaRecorder::MediaRecorder(){
const sp<IMediaPlayerService>& service(getMediaPlayerService());
if (service != NULL) {
mMediaRecorder = service->createMediaRecorder(getpid());
}
18
19. 5.RecordThread의 생성 안드로이드의 모든것 분석과 포팅 정리
Recorder.java StagefrightRecorder.cpp
public void startRecording{ sp<MediaSource> StagefrightRecorder::createAudioSource()
.. {
mRecorder.start(); …
sp<AudioSource> audioSource =
new AudioSource(
mAudioSource,
mSampleRate,
status_t StagefrightRecorder::start() {
mAudioChannels);
…
}
case OUTPUT_FORMAT_DEFAULT:
case OUTPUT_FORMAT_THREE_GPP:
case OUTPUT_FORMAT_MPEG_4:
return startMPEG4Recording();
AudioSource.cpp
AudioSource::AudioSource(…)
{
status_t StagefrightRecorder::startMPEG4Recording() {
…
sp<MediaWriter> writer = new MPEG4Writer(dup(mOutputFd));
mRecord = new AudioRecord(
err = setupAudioEncoder(writer);
inputSource,
sampleRate,
AudioSystem::PCM_16_BIT,
status_t StagefrightRecorder::setupAudioEncoder(const channels > 1?
sp<MediaWriter>& writer) AudioSystem::CHANNEL_IN_STEREO:
{ AudioSystem::CHANNEL_IN_MONO,
… 4 * kMaxBufferSize / sizeof(int16_t),
switch(mAudioEncoder) { flags);
case AUDIO_ENCODER_AMR_NB: }
case AUDIO_ENCODER_AMR_WB:
case AUDIO_ENCODER_AAC:
audioEncoder = createAudioSource();
19
20. 5.RecordThread의 생성 안드로이드의 모든것 분석과 포팅 정리
AudioRecord.cpp
AudioRecord::AudioRecord(…){
{
mStatus = set(inputSource, sampleRate, format, channels,
frameCount, flags, cbf, user, notificationFrames, sessionId);
}
status_t AudioRecord::set(…)
{
audio_io_handle_t input = AudioSystem::getInput(inputSource,
sampleRate, format, channels,
(AudioSystem::audio_in_acoustics)flags);
}
AudioSystem.cpp
audio_io_handle_t AudioSystem::getInput(int inputSource,
uint32_t samplingRate,
uint32_t format,
uint32_t channels,
audio_in_acoustics acoustics)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return 0;
return aps->getInput(inputSource, samplingRate, format, channels, acoustics);
}
20
21. 5.RecordThread의 생성 안드로이드의 모든것 분석과 포팅 정리
audio_io_handle_t AudioPolicyService::getInput(…)
{
Mutex::Autolock _l(mLock);
return mpPolicyManager->getInput(inputSource, samplingRate, format, channels, acoustics);
}
mpPolicyManager는 AudioPolicyManagerALSA class를 가리키는데 이 class는 AudioPolicyManagerBase를
상속받는다. 그래서 getInput method는 AudioPolicyManagerBase에 정의된 것을 사용한다.
AudioPolicyManagerBase.cpp
audio_io_handle_t AudioPolicyManagerBase::getInput(…){
inputDesc->mInputSource = inputSource;
inputDesc->mDevice = device;
inputDesc->mSamplingRate = samplingRate;
inputDesc->mFormat = format;
inputDesc->mChannels = channels;
inputDesc->mAcoustics = acoustics;
inputDesc->mRefCount = 0;
input = mpClientInterface->openInput(&inputDesc->mDevice,
&inputDesc->mSamplingRate,
&inputDesc->mFormat,
&inputDesc->mChannels,
inputDesc->mAcoustics);
}
AudioPolicyService.cpp
audio_io_handle_t AudioPolicyService::openInput(…)
{
sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
return af->openInput(pDevices, pSamplingRate, (uint32_t *)pFormat, pChannels, acoustics);
}
21
22. 5.RecordThread의 생성 안드로이드의 모든것 분석과 포팅 정리
int AudioFlinger::openInput(…)
{
…
AudioStreamIn *input = mAudioHardware->openInputStream(*pDevices,
(int *)&format,
&channels,
&samplingRate,
&status,
mAudioHardware 는 AudioHardwareALSA 를 가리킨다.
AudioHardwareALSA::openInputStream는 alsa_omap3.cpp 에 있는 s_open을 호출해서 PCM device를 open하고 HAL 의
AudioStreamInALSA를 생성한다.
int id = nextUniqueId(); unique한 id를 생성하고
thread = new RecordThread(this, input, reqSamplingRate, reqChannels, id); 그 id로 RecordThread생성
mRecordThreads.add(id, thread);
생성된 RecordThread를 mRecordThreads에 추가한다. AudioFlinger
return id; RecordThread id를 return함. AudioBufferProvider
RecordThread
AudioHardwareInterface
AudioStreamInALSA
22
23. 6. DuplicatingThread의 생성 안드로이드의 모든것 분석과 포팅 정리
안드로이드 시스템이 두 개의 디바이스로 동시에 출력 할 경우 DuplicatingThread 를 사용한다.
AudioService.java
AudioSystem.setDeviceConnectionState(device, AudioSystem.DEVICE_STATE_AVAILABLE, address);
AudioSystem.cpp
status_t AudioSystem::setDeviceConnectionState(audio_devices device,
device_connection_state state,
const char *device_address)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
return aps->setDeviceConnectionState(device, state, device_address);
}
AudioPolicyService.cpp
status_t AudioPolicyService::setDeviceConnectionState(…)
{
…
return mpPolicyManager->setDeviceConnectionState(device, state, device_address);
}
AudioPolicyManagerALSA.cpp
status_t AudioPolicyManagerALSA::setDeviceConnectionState(…)
{
…
if (AudioSystem::isA2dpDevice(device)) {
status_t status = handleA2dpConnection(device, device_address);
23
24. 6. DuplicatingThread의 생성 안드로이드의 모든것 분석과 포팅 정리
AudioPolicyMangerALSA.cpp
status_t AudioPolicyManagerALSA::setDeviceConnectionState(…)
{
…
if (AudioSystem::isA2dpDevice(device)) {
status_t status = handleA2dpConnection(device, device_address);
}
}
status_t AudioPolicyManagerBase::handleA2dpConnection(…)
{
…
mA2dpOutput = mpClientInterface->openOutput(&outputDesc->mDevice,
&outputDesc->mSamplingRate,
&outputDesc->mFormat,
&outputDesc->mChannels,
&outputDesc->mLatency,
outputDesc->mFlags);
Bluetooth 디바이스 출력을 위한 playbackthread(mixerthread)생성(mPlaybackThreads에 add 됨.)
mDuplicatedOutput = mpClientInterface->openDuplicateOutput(mA2dpOutput, mHardwareOutput);
}
audio_io_handle_t AudioPolicyService::openDuplicateOutput(…){
sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
return af->openDuplicateOutput(output1, output2);
}
24
25. 6. DuplicatingThread의 생성 안드로이드의 모든것 분석과 포팅 정리
int AudioFlinger::openDuplicateOutput(int output1, int output2)
{
..
MixerThread *thread1 = checkMixerThread_l(output1);
output1은 mA2dpOutput 을 가리 킴. 즉, handleA2dpConnection에서 생성한 bluetooth mixerthread를
mPlaybackThreads 에서 가져 옴.
MixerThread *thread2 = checkMixerThread_l(output2);
output2는 mHardwareOutput를 가리킴. 기존에 생성되어진 mixerthread를 가리킴.
DuplicatingThread *thread = new DuplicatingThread(this, thread1, id);
DuplicatingThread를 생성하면서 thread1(bluetooth thread)를 moutputTracks에 add한다.
thread->addOutputTrack(thread2);
DuplicatingThread의 moutputTracks에 기존의 mixerthread를 add한다.
mPlaybackThreads.add(id, thread);
mPlaybackThreads.add에 DuplicatingThread를 add한다.
..
} AudioFlinger
mPlaybackThreads
DuplicatingThread
BT mixerthread 기존 mixerthread
25