Android音頻系統之AudioFlinger(一)


1.1 AudioFlinger

在上面的框架圖中,我們可以看到AudioFlinger(下面簡稱AF)是整個音頻系統的核心與難點。作為Android系統中的音頻中樞,它同時也是一個系統服務,啟到承上(為上層提供訪問接口)啟下(通過HAL來管理音頻設備)的作用。只有理解了AudioFlinger,才能以此為基礎更好地深入到其它模塊,因而我們把它放在前面進行分析。

 

1.1.1 AudioFlinger服務的啟動和運行

我們知道,Android中的系統服務分為兩類,分別是Java層和Native層的System Services。其中AudioFlinger和SurfaceFlinger一樣,都屬於后者。Java層服務通常在SystemServer.java中啟動,比如后面會看到的AudioService就是這種情況。而Native層服務則通常是各服務方按照自己的特定部署來決定何時啟動、如何啟動。例如AudioFlinger就是利用一個Linux程序來間接創建的,如下所示:

/*frameworks/av/media/mediaserver/main_mediaserver.cpp*/

int main(int argc, char** argv)

{

    sp<ProcessState>proc(ProcessState::self());

    sp<IServiceManager>sm = defaultServiceManager();

   ALOGI("ServiceManager: %p", sm.get());

   AudioFlinger::instantiate();

   MediaPlayerService::instantiate();

   CameraService::instantiate();

   AudioPolicyService::instantiate();

   ProcessState::self()->startThreadPool();

   IPCThreadState::self()->joinThreadPool();

}

這個mediaserver的目錄下只有一個文件,它的任務很簡單,就是把所有媒體相關的native層服務(包括AudioFlinger,MediaPlayerService,CameraService和AudioPolicyService)啟動起來,可以參考其Android.mk:

LOCAL_SRC_FILES:= \

                main_mediaserver.cpp

 

LOCAL_SHARED_LIBRARIES := \

                libaudioflinger\

                libcameraservice\

                libmediaplayerservice\

                libutils \

                libbinder

LOCAL_MODULE:= mediaserver

根據前面的分析,AudioFlinger的源碼實現是放在libaudioflinger庫中的,因而在編譯mediaserver時要引用這個庫,其它服務也是一樣的做法。編譯生成的mediaserver將被燒錄到設備的/system/bin/mediaserver路徑中,然后由系統啟動時的init進程啟動,其在Init.rc中的配置是:

service media /system/bin/mediaserver

    class main

    user media

    group audio camera inetnet_bt net_bt_admin net_bw_acct drmrpc

    ioprio rt 4

值得一提的是,這個AudioFlinger::instantiate()並不是AudioFlinger內部的靜態類,而是BinderService類的一個實現。包括AudioFlinger、AudioPolicyService等在內的幾個服務都繼承自這個統一的Binder服務類,比如:

class AudioFlinger :

    public BinderService<AudioFlinger>,

    public BnAudioFlinger…

從名稱上看,BinderService應該是實現了binder跨進程通信相關的功能,它是一個模板類,其中的函數instantiate將把模板指定的服務創建出來,並添加到ServiceManager中:

   /*frameworks/native/include/binder/BinderService.h*/

    template<typename SERVICE> …

    static status_t  publish(bool allowIsolated = false) {

       sp<IServiceManager> sm(defaultServiceManager());

        returnsm->addService(String16(SERVICE::getServiceName()), new SERVICE(),allowIsolated);

    }

    static void instantiate(){ publish(); } //調用publish

回頭看下AudioFlinger的構造函數,發現它只是簡單地為內部一些變量做了初始化,除此之外就沒有任何代碼了:

(frameworks/av/services/audioflinger)

AudioFlinger::AudioFlinger()

:BnAudioFlinger(),mPrimaryHardwareDev(NULL),

 mHardwareStatus(AUDIO_HW_IDLE), // see alsoonFirstRef()

      mMasterVolume(1.0f),mMasterVolumeSupportLvl(MVS_NONE), mMasterMute(false),

      mNextUniqueId(1),mMode(AUDIO_MODE_INVALID), mBtNrecIsOff(false)

{

}

大家可能會覺得疑惑,那么AudioFlinger在什么情況下會開始執行實際的工作呢?沒錯,是在onFirstRef()中。BnAudioFlinger是由RefBase層層繼承而來的,並且IServiceManager::addService的第二個參數實際上是一個強指針引用(constsp<IBinder>&),因而AudioFlinger具備了強指針被第一次引用時調用onFirstRef的程序邏輯。如果大家不是很清楚這些細節的話,可以參考下本書的強指針章節,這里不再贅述。

void AudioFlinger::onFirstRef()

{

    int rc = 0;

    Mutex::Autolock _l(mLock);

    charval_str[PROPERTY_VALUE_MAX] = { 0 };

    if(property_get("ro.audio.flinger_standbytime_ms", val_str, NULL) >=0) {

        uint32_t int_val;

        if (1 ==sscanf(val_str, "%u", &int_val)) {

            mStandbyTimeInNsecs= milliseconds(int_val);

            ALOGI("Using%u mSec as standby time.", int_val);

        } else {

           mStandbyTimeInNsecs = kDefaultStandbyTimeInNsecs;

            …

        }

}

mMode = AUDIO_MODE_NORMAL;

    mMasterVolumeSW = 1.0;

    mMasterVolume   = 1.0;

    mHardwareStatus =AUDIO_HW_IDLE;

}

屬性ro.audio.flinger_standbytime_ms為用戶調整standby時間提供了一個接口,早期版本中這個時間值是固定的。接下來初始化幾個重要的內部變量,和構造函數的做法不同的是,這里賦予的都是有效的值了。

從這時開始,AudioFlinger就是一個“有意義”的實體了,因為有人使用到了它。接下來其它進程可以通過ServiceManager來訪問,並調用createTrack、openOutput等一系列接口來驅使AudioFlinger執行音頻處理操作,我們在后面章節會陸續講解到。

版權聲明:本文為博主原創文章,未經博主允許不得轉載。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM