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階段主要是由@
Wireshark之FTP協議分析(二)
以實際抓包來分析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中我們將構建一個兩層的神經網路,並進行訓練
(O)Telephony分析之通話流程分析(二)撥打電話流程分析(上)
撥打電話,是從通話的撥號盤開始的,而撥號盤的介面是在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鍵界面錯亂(二) 你確定你了解分屏的整個流