1. 程式人生 > >AndroidO audio系統之audioflinger啟動分析(二)

AndroidO audio系統之audioflinger啟動分析(二)

1. audioflinger建立過程

在Android8.0的音訊系統中,AudioFlinger是一個C++的Binder服務,執行在HAL程序中,它是在audioserver.c

//frameworks/av/media/audioserver/audioserver.rc
service audioserver /system/bin/audioserver
    class main
    user audioserver
    # media gid needed for /dev/fm (radio) and for /data/misc/media (tee)
    group audio camera drmrpc inet media mediadrm net_bt net_bt_admin net_bw_acct oem_2901
    ioprio rt 4
writepid /dev/cpuset/foreground/tasks /dev/stune/foreground/tasks onrestart restart audio-hal-2-0 on property:vts.native_server.on=1 stop audioserver on property:vts.native_server.on=0 start audioserver

audioserver的入口函式是main(),程式碼如下:

int main(int argc __unused, char **argv)
{
    ......
    sp<
ProcessState> proc(ProcessState::self()); sp<IServiceManager> sm = defaultServiceManager(); ALOGI("ServiceManager: %p", sm.get()); AudioFlinger::instantiate(); //建立AudioFlinger服務 AudioPolicyService::instantiate(); //建立AudioPolicyService服務 AAudioService::instantiate
(); //建立AAudioService服務 RadioService::instantiate(); //建立RadioService服務 SoundTriggerHwService::instantiate(); #ifdef VRAUDIOSERVICE_ENABLE VRAudioServiceNative::instantiate(); #endif ProcessState::self()->startThreadPool(); // FIXME: remove when BUG 31748996 is fixed android::hardware::ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool(); }

AudioFlinger::instantiate()並不屬於AudioFlinger的內部類,而是BinderService類的一個實現包括AudioFlinger,AudioPolicy等在內的幾個服務都繼承自這個統一的Binder的服務類,具體實現在BinderService.h中

// frameworks/native/include/binder/BinderService.h
    static status_t publish(bool allowIsolated = false) {
        sp<IServiceManager> sm(defaultServiceManager());
        //SERVICE是檔案中定義的一個模板,AudioFlinger呼叫了instantiate()函式,
        //所以當前的SERVICE為AudioFlinger
        return sm->addService(
                String16(SERVICE::getServiceName()),
                new SERVICE(), allowIsolated);
    }

    static void instantiate() { publish(); }

可以看出publish()函式所做的事獲取到ServiceManager的代理,然後new一個呼叫instantiate的那個service的物件並把它新增到ServiceManager中。
所以下一步就是去分析AudioFlinger的構造函數了

AudioFlinger::AudioFlinger()
    : BnAudioFlinger(),
      mMediaLogNotifier(new AudioFlinger::MediaLogNotifier()),
      mPrimaryHardwareDev(NULL),
      mAudioHwDevs(NULL),
      mHardwareStatus(AUDIO_HW_IDLE),
      mMasterVolume(1.0f),
      mMasterMute(false),
      // mNextUniqueId(AUDIO_UNIQUE_ID_USE_MAX),
      mMode(AUDIO_MODE_INVALID),
      mBtNrecIsOff(false),
      mIsLowRamDevice(true),
      mIsDeviceTypeKnown(false),
      mGlobalEffectEnableTime(0),
      mSystemReady(false)
{
    // unsigned instead of audio_unique_id_use_t, because ++ operator is unavailable for enum
    for (unsigned use = AUDIO_UNIQUE_ID_USE_UNSPECIFIED; use < AUDIO_UNIQUE_ID_USE_MAX; use++) {
        // zero ID has a special meaning, so unavailable
        mNextUniqueIds[use] = AUDIO_UNIQUE_ID_USE_MAX;
    }

    getpid_cached = getpid();
    const bool doLog = property_get_bool("ro.test_harness", false);
    if (doLog) {
        mLogMemoryDealer = new MemoryDealer(kLogMemorySize, "LogWriters",
                MemoryHeapBase::READ_ONLY);
        (void) pthread_once(&sMediaLogOnce, sMediaLogInit);
    }

    // reset battery stats.
    // if the audio service has crashed, battery stats could be left
    // in bad state, reset the state upon service start.
    //重置電池統計資訊。 如果音訊服務崩潰,電池狀態可能會處於不良狀態,在服務啟動時重置狀態
    BatteryNotifier::getInstance().noteResetAudio();

    //建立裝置HAL層介面,用於hidl繫結
    mDevicesFactoryHal = DevicesFactoryHalInterface::create();
    //建立效果HAL層介面,用於hidl繫結
    mEffectsFactoryHal = EffectsFactoryHalInterface::create();

    mMediaLogNotifier->run("MediaLogNotifier");
}

1.1 DevicesFactoryHalInterface

sp<DevicesFactoryHalInterface> DevicesFactoryHalInterface::create() {
    return new DevicesFactoryHalHybrid();
}

DevicesFactoryHalHybrid::DevicesFactoryHalHybrid()
        : mLocalFactory(new DevicesFactoryHalLocal()),
          mHidlFactory(
#ifdef USE_LEGACY_LOCAL_AUDIO_HAL
                  nullptr
#else
                  new DevicesFactoryHalHidl()
#endif
                       ) {
}

DevicesFactoryHalHybrid::~DevicesFactoryHalHybrid() {
}

1.2 EffectsFactoryHalInterface

sp<EffectsFactoryHalInterface> EffectsFactoryHalInterface::create() {
    return new EffectsFactoryHalHidl();
}

EffectsFactoryHalHidl::EffectsFactoryHalHidl() : ConversionHelperHidl("EffectsFactory") {
    mEffectsFactory = IEffectsFactory::getService();
    if (mEffectsFactory == 0) {
        ALOGE("Failed to obtain IEffectsFactory service, terminating process.");
        exit(1);
    }
}

接下來再看看它的onFirstRef()函式。

void AudioFlinger::onFirstRef()
{
    Mutex::Autolock _l(mLock);

    /* TODO: move all this work into an Init() function */
    char val_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;
            ALOGI("Using default %u mSec as standby time.",
                    (uint32_t)(mStandbyTimeInNsecs / 1000000));
        }
    }

    mPatchPanel = new PatchPanel(this);

    mMode = AUDIO_MODE_NORMAL;

    gAudioFlinger = this;
}

onFirstRef()函式也很簡單,僅僅讀取屬性”ro.audio.flinger_standbytime_ms”的值並賦給變數mStandbyTimeInNsecs ,若這個屬性沒有設定,則使用預設值kDefaultStandbyTimeInNsecs。

2. audioflinger中的執行緒關係圖

執行緒結構圖
    PlaybackThread和RecordThread分別用於播放與錄音。PlaybackThread中派生出DirectOutputThread與MixerThread。AudioFlinger中建立的播放執行緒大都是MixerThread,用於混合多路聲音輸出,而DirectOutputThread用於將聲音直接傳送給底層播放,不需要混音處理。
  DuplicatingThread用於將聲音同時輸出到藍芽裝置和其他裝置,因為藍芽裝置和其他裝置的連線是分開的,所以輸出藍芽音訊資料需要一條單獨的通道,而輸出到DSP的資料也需要一條單獨的通道。

3.小結

    本文旨在介紹一下audioflinger的啟動過程及它包含執行緒之間的關係。具體audioflinger是如何工作的?後面會深入的一步步分析。下一篇將會先介紹audiopolicyservice以及它如何關聯audioflinger等等,未完待續。。。

相關推薦

AndroidO audio系統audioflinger啟動分析

1. audioflinger建立過程 在Android8.0的音訊系統中,AudioFlinger是一個C++的Binder服務,執行在HAL程序中,它是在audioserver.c //frameworks/av/media/audioserver/

FAT16檔案系統目錄項分析

FAT16檔案系統的FDT分析 1:FDT位置 FDT的含義為檔案目錄表,它在一個檔案系統中的具體位置是緊跟在FAT2之後。 定位過程: A:系統通過讀取該分割槽表資訊,定位到其DBR扇區 B:讀取DBR的保留扇區數(OEH –0FH). C:讀取每個FAT扇區數(16H

聊聊高併發系統限流特技(轉)

上一篇《聊聊高併發系統限流特技-1》講了限流演算法、應用級限流、分散式限流;本篇將介紹接入層限流實現。 接入層限流 接入層通常指請求流量的入口,該層的主要目的有:負載均衡、非法請求過濾、請求聚合、快取、降級、限流、 A/B 測試、服務質量監控

SpringBoot實現Java高併發秒殺系統Service層開發

繼上一篇文章:SpringBoot實現Java高併發秒殺系統之DAO層開發 我們建立了SpringBoot專案並熟悉了秒殺系統的表設計,下面我們將講解一下秒殺系統的核心部分:Service業務層的開發。 Service層又稱為業務層,在Spring階段主要是由@

WiresharkFTP協議分析

以實際抓包來分析ftp協議,加深理解。 環境: win7電腦+linux裝置,linux裝置為ftp服務端,win7電腦通過WinSCP的ftp主動方式(我得版本winscp預設是被動方式,需要從高階選項修改)來連線ftp服務端。 過程: 電腦(192.168.3.2

資料探勘演算法聚類分析canopy演算法

canopy是聚類演算法的一種實現 它是一種快速,簡單,但是不太準確的聚類演算法 canopy通過兩個人為確定的閾值t1,t2來對資料進行計算,可以達到將一堆混亂的資料分類成有一定規則的n個數據堆 由於canopy演算法本身的目的只是將混亂的資料劃分成大概的幾個類別,所以它

神經網路文字情感分析

Projet 2 在Project 1 中,我們學習瞭如何處理和統計reviews 基於上一個Project”一個蘿蔔一個坑”的思想,我們將文字進行了數字化,使得文字可以作為輸入進行訓練 在Project 2中我們將構建一個兩層的神經網路,並進行訓練

OTelephony分析通話流程分析撥打電話流程分析

撥打電話,是從通話的撥號盤開始的,而撥號盤的介面是在DialpadFragment,因此,需要從這個地方進行分析一.撥號盤介面撥號流程 public void onClick(View view) { ...... if (resId == R.id.dia

FAT32檔案系統的FAT表分析

1.      FAT表的作用及結構特點 FAT32與FAT16表的作用和結構類似,這裡只道不同 A:FAT32的FAT表也是由FAT表項構成的,每個FAT項的大小為4個位元組 B:FAT項的大小為4個位元組,即32位,但是隻用到了26位,最多管理226 =671088

機房收費系統結賬與報表週報表製作《一學就會傻瓜版》

如果你對機房收費系統的結賬與日結賬、周結賬的關係資料庫表不清楚、可以先補補課 有錯請及時指出、有錯必改、方便大家! 我們要用一個軟體做報表的模板、然後在VB裡面新增部件、程式碼呼叫模板,

Java併發AQS原始碼分析

我在Java併發之AQS原始碼分析(一)這篇文章中,從原始碼的角度深度剖析了 AQS 獨佔鎖模式下的獲取鎖與釋放鎖的邏輯,如果你把

Java安全Commons Collections1分析

# Java安全之Commons Collections1分析(二) ## 0x00 前言 續上篇文,繼續除錯cc鏈。在上篇文章除錯的cc鏈其實並不是一個完整的鏈。只是使用了幾個方法的的互相呼叫彈出一個計算器。 [Java安全之Commons Collections1分析(一)](https://www

AndroidO audio系統框架簡介

1、概述        Audio系統在Android中負責音訊方面的資料流傳輸和控制功能,也負責音訊裝置的管理,它是Android中最複雜的子系統之一。本文將粗略分析一下audio的整體框架及播放、錄製流程。不足之處,敬請指正,謝謝! 2、音訊框架圖

Android編譯系統分析幾個關鍵點

已開通新的部落格,後續文字都會發到新部落格 http://www.0xfree.top Android 編譯系統解析系列文件 解析lunch的執行過程以及make執行過程中include檔案的順序 Android編譯系統分析之lunch分析 Android

elasticsearch原始碼分析啟動過程

最近開始廣泛的使用elasticsearch,也開始寫一些java程式碼了,為了提高java程式碼能力,也為了更加深入一點了解elasticsearch的內部運作機制,所以開始看一些elasticsearch的原始碼了。對於這種廣受追捧的開源專案,細細品讀一定會受益匪淺,

MyBatis啟動分析

前言 MyBatis 作為目前最常用的持久層框架之一,分析其原始碼,對我們的使用過程中可更好的運用它。本系列基於mybatis-

linux設備驅動misc驅動框架源碼分析

linux驅動開發misc設備驅動1、misc_open函數分析 該函數在driver/char/misc.c中,misc.c是驅動框架實現的,這裏面的misc_Open函數是misc驅動框架為應用層提供的一個打開misc設備的一個接口。 1、首先我們要知道在misc.c中的misc_init函數

操作系統進程管理2

操作 交叉 管理 臨界資源 uid 臨界區 http 系統 php 進程管理(course 2) 一、進程互斥 由於進程具有獨立性和異步性等並發特征,計算機的資源有限,導致了進程之間的資源競爭和共享,也導致了對進程執行過程的制約。 1、臨界資源和臨界區(臨界部分) 臨界資源

Ocata Neutron代碼分析——Neutron RPC啟動過程分析

gre add ice common multi tween wait函數 tex 依次 RPC啟動跟Neutron API的啟動在同一個函數中執行,neutron.server.wsgi_eventlet.py中的eventlet_wsgi_server。 def ev

google 分屏 橫屏模式 按home鍵界面錯亂故障分析 分屏的啟動過程

activity 根據 動作 home鍵 更新 lean 全屏 擴展 ddt google 進入分屏後在橫屏模式按home鍵界面錯亂(二) 你確定你了解分屏的整個流