안드로이드의 모든것 분석과 포팅 정리




Android Audio System
   (AudioFlinger)




                                박철희

                          1
1.Audio system 전체 구조                                                 안드로이드의 모든것 분석과 포팅 정리



Application   Media player App   Media Recorder App   Volume /mode change




Application
Framework




Native
Framework




HAL




Kernel



                                                                                2
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
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
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
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
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
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
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
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
2.AudioFlinger class 구조                                                    안드로이드의 모든것 분석과 포팅 정리

                                          BnAudioFlinger



                                         AudioFlinger

                                                Thread


                                           ThreadBase

                                          AudioBufferProvider

                                                TrackBase



                                 BnAudioTrack                                  AudioBufferProvider
        playbackThread

                                                                                                     BnAudioRecord
             Track                TrackHandle
                                                                RecordThread

           outputTrack
                                                                 RecordTrack                          RecordHandle




      MixerThread         DirectoutputThread



    DuplicatingThread




                                                                                                      11
3.IAudioFlinger 인터페이스                                  안드로이드의 모든것 분석과 포팅 정리




                            IInterface




                           IAudioFlinger




          BnAudioFlinger                                BpAudioFlinger




                               virtual sp<IAudioTrack> createTrack,
                              virtual sp<IAudioRecord> openRecord,
           AudioFlinger        virtual int openOutput,
                              setMasterVolume,
                              setMicMute
                              …




                                                                         12
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
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
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
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
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
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
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
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
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
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
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
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
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

More Related Content

PPTX
Android audio system(audio_hardwareinterace)
PDF
Embedded Android : System Development - Part III (Audio / Video HAL)
PPT
Android Audio System
PPTX
Android audio system(오디오 출력-트랙생성)
PPTX
Android audio system(audiopolicy_manager)
PPTX
Android audio system(audioplicy_service)
PDF
Android Multimedia Framework
PPTX
Android audio system(오디오 플링거 서비스 초기화)
Android audio system(audio_hardwareinterace)
Embedded Android : System Development - Part III (Audio / Video HAL)
Android Audio System
Android audio system(오디오 출력-트랙생성)
Android audio system(audiopolicy_manager)
Android audio system(audioplicy_service)
Android Multimedia Framework
Android audio system(오디오 플링거 서비스 초기화)

What's hot (20)

PDF
Android's Multimedia Framework
PDF
Embedded Android : System Development - Part IV
PDF
The Android graphics path, in depth
PPT
Learning AOSP - Android Linux Device Driver
PPT
Android booting sequece and setup and debugging
PDF
Embedded Android : System Development - Part I
ODP
Embedded Android : System Development - Part III
PDF
Embedded Android : System Development - Part II (HAL)
PDF
Android Things : Building Embedded Devices
ODP
Q4.11: Porting Android to new Platforms
PDF
Using and Customizing the Android Framework / part 4 of Embedded Android Work...
PDF
Explore Android Internals
PDF
Embedded Android : System Development - Part II (Linux device drivers)
PDF
Understanding the Android System Server
PDF
Booting Android: bootloaders, fastboot and boot images
PPT
"Learning AOSP" - Android Hardware Abstraction Layer (HAL)
PDF
Audio Drivers
PPT
Learning AOSP - Android Booting Process
PPT
Linux Audio Drivers. ALSA
PDF
MediaPlayer Playing Flow
Android's Multimedia Framework
Embedded Android : System Development - Part IV
The Android graphics path, in depth
Learning AOSP - Android Linux Device Driver
Android booting sequece and setup and debugging
Embedded Android : System Development - Part I
Embedded Android : System Development - Part III
Embedded Android : System Development - Part II (HAL)
Android Things : Building Embedded Devices
Q4.11: Porting Android to new Platforms
Using and Customizing the Android Framework / part 4 of Embedded Android Work...
Explore Android Internals
Embedded Android : System Development - Part II (Linux device drivers)
Understanding the Android System Server
Booting Android: bootloaders, fastboot and boot images
"Learning AOSP" - Android Hardware Abstraction Layer (HAL)
Audio Drivers
Learning AOSP - Android Booting Process
Linux Audio Drivers. ALSA
MediaPlayer Playing Flow
Ad

More from fefe7270 (16)

PPTX
Surface flingerservice(서피스 출력 요청 jb)
PPTX
Surface flingerservice(서피스 상태 변경 jb)
PPTX
Surface flingerservice(서피스 플링거 연결 jb)
PPTX
Surface flingerservice(서피스플링거서비스초기화 jb)
PPTX
Surface flingerservice(서피스 플링거 연결 ics)
PPTX
Surface flingerservice(서피스플링거서비스초기화 ics)
PPTX
Surface flingerservice(그래픽 공유 버퍼 생성 및 등록)
PPTX
Surface flingerservice(서피스 상태 변경 및 출력 요청)
PPTX
Surface flingerservice(서피스 플링거 연결)
PPTX
Surface flingerservice(서피스플링거서비스초기화)
PPT
Stagefright recorder part1
PPTX
Camera camcorder framework overview(ginger bread)
PPTX
C++정리 스마트포인터
PPTX
Android audio system(pcm데이터출력준비-서비스서버)
PPTX
Android audio system(pcm데이터출력요청-서비스클라이언트)
PPTX
Android audio system(오디오 출력-트랙활성화)
Surface flingerservice(서피스 출력 요청 jb)
Surface flingerservice(서피스 상태 변경 jb)
Surface flingerservice(서피스 플링거 연결 jb)
Surface flingerservice(서피스플링거서비스초기화 jb)
Surface flingerservice(서피스 플링거 연결 ics)
Surface flingerservice(서피스플링거서비스초기화 ics)
Surface flingerservice(그래픽 공유 버퍼 생성 및 등록)
Surface flingerservice(서피스 상태 변경 및 출력 요청)
Surface flingerservice(서피스 플링거 연결)
Surface flingerservice(서피스플링거서비스초기화)
Stagefright recorder part1
Camera camcorder framework overview(ginger bread)
C++정리 스마트포인터
Android audio system(pcm데이터출력준비-서비스서버)
Android audio system(pcm데이터출력요청-서비스클라이언트)
Android audio system(오디오 출력-트랙활성화)
Ad

Recently uploaded (20)

PPTX
The various Industrial Revolutions .pptx
PPTX
Benefits of Physical activity for teenagers.pptx
PDF
Improvisation in detection of pomegranate leaf disease using transfer learni...
PPTX
Chapter 5: Probability Theory and Statistics
PPTX
2018-HIPAA-Renewal-Training for executives
PPT
Galois Field Theory of Risk: A Perspective, Protocol, and Mathematical Backgr...
PDF
Developing a website for English-speaking practice to English as a foreign la...
PDF
Flame analysis and combustion estimation using large language and vision assi...
PDF
Getting started with AI Agents and Multi-Agent Systems
PDF
The influence of sentiment analysis in enhancing early warning system model f...
PPT
Module 1.ppt Iot fundamentals and Architecture
PDF
ENT215_Completing-a-large-scale-migration-and-modernization-with-AWS.pdf
PDF
1 - Historical Antecedents, Social Consideration.pdf
PDF
CloudStack 4.21: First Look Webinar slides
PPTX
Modernising the Digital Integration Hub
PPTX
AI IN MARKETING- PRESENTED BY ANWAR KABIR 1st June 2025.pptx
PDF
sbt 2.0: go big (Scala Days 2025 edition)
PDF
A proposed approach for plagiarism detection in Myanmar Unicode text
PDF
STKI Israel Market Study 2025 version august
PDF
Produktkatalog für HOBO Datenlogger, Wetterstationen, Sensoren, Software und ...
The various Industrial Revolutions .pptx
Benefits of Physical activity for teenagers.pptx
Improvisation in detection of pomegranate leaf disease using transfer learni...
Chapter 5: Probability Theory and Statistics
2018-HIPAA-Renewal-Training for executives
Galois Field Theory of Risk: A Perspective, Protocol, and Mathematical Backgr...
Developing a website for English-speaking practice to English as a foreign la...
Flame analysis and combustion estimation using large language and vision assi...
Getting started with AI Agents and Multi-Agent Systems
The influence of sentiment analysis in enhancing early warning system model f...
Module 1.ppt Iot fundamentals and Architecture
ENT215_Completing-a-large-scale-migration-and-modernization-with-AWS.pdf
1 - Historical Antecedents, Social Consideration.pdf
CloudStack 4.21: First Look Webinar slides
Modernising the Digital Integration Hub
AI IN MARKETING- PRESENTED BY ANWAR KABIR 1st June 2025.pptx
sbt 2.0: go big (Scala Days 2025 edition)
A proposed approach for plagiarism detection in Myanmar Unicode text
STKI Israel Market Study 2025 version august
Produktkatalog für HOBO Datenlogger, Wetterstationen, Sensoren, Software und ...

Android audio system(audioflinger)

  • 1. 안드로이드의 모든것 분석과 포팅 정리 Android Audio System (AudioFlinger) 박철희 1
  • 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