AudioPolicyService和AudioFlinger都駐留于一個進程,之前在MixerThread來歷一節中,曾簡單介紹過APS的創建,現在需要仔細觀察其中的內容。
1. 創建 AudioPolicyService
AudioPolicyService的代碼如下所示:
**AudioPolicyService.cpp**
~~~
AudioPolicyService::AudioPolicyService()
:BnAudioPolicyService() ,
//mpPolicyManager是Audio系統中的另一種HAL對象,它的類型是AudioPolicyInterface
mpPolicyManager(NULL)
{
char value[PROPERTY_VALUE_MAX];
//TonePlayback用于播放Tone音,Tone包括按鍵音等
mTonePlaybackThread = new AudioCommandThread(String8(""));
//用于處理控制命令,例如路由切換、音量調節等
mAudioCommandThread = newAudioCommandThread(String8("ApmCommandThread"));
#if (defined GENERIC_AUDIO) || (definedAUDIO_POLICY_TEST)
//注意AudioPolicyManagerBase的構造函數,把this傳進去了。
mpPolicyManager = new AudioPolicyManagerBase(this);
#else
...
//使用硬件廠商實現的AudioPolicyInterface
mpPolicyManager= createAudioPolicyManager(this);
#endif
//根據系統屬性來判斷照相機拍照時是否強制發聲。為了防止偷拍,強制按快門的時候必須發出聲音。
property_get("ro.camera.sound.forced",value, "0");
mpPolicyManager->setSystemProperty("ro.camera.sound.forced",value);
}
~~~
和AudioFlinger中的AudioHardwareInterface一樣,在APS中可以見到另外一個HAL層對象AudioPolicyInterface,為什么在APS中也會存在HAL對象呢?
如前所述,APS主要是用來控制Audio系統的,由于各個硬件廠商的控制策略不可能完全一致,所以Android把這些內容抽象成一個HAL對象。下面來看這個AudioPolicyInterface。
2. 對AudioPolicyInterface的分析
AudioPolicyInterface比AudioHardwareInterface簡單直接。這里,只需看幾個重點函數即可,代碼如下所示:
**AudioPolicyInterface.h**
~~~
class AudioPolicyInterface
{
public:
......
//設置設備的連接狀態,這些設備有耳機、藍牙等
virtualstatus_t setDeviceConnectionState(
AudioSystem::audio_devicesdevice,
AudioSystem::device_connection_state state,
const char *device_address) = 0;
//設置系統Phone狀態,這些狀態包括通話狀態、來電狀態等
virtual void setPhoneState(int state) = 0;
//設置force_use的config策略,例如通話中強制使用揚聲器
virtualvoid setForceUse(AudioSystem::force_use usage,
AudioSystem::forced_config config) = 0;
/*
audio_io_handle_t是int類型。這個函數的目的是根據傳入的參數類型
找到合適的輸出句柄。這個句柄,在目前的Audio系統代表AF中的某個工作線程。
還記得創建AudioTrack的時候傳入的那個output值嗎?它就是通過這個函數得來的。
關于這個問題,馬上會分析到
*/
virtualaudio_io_handle_t getOutput(
AudioSystem::stream_typestream,
uint32_t samplingRate = 0,
uint32_t format = AudioSystem::FORMAT_DEFAULT,
uint32_t channels = 0,
AudioSystem::output_flagsflags =
AudioSystem::OUTPUT_FLAG_INDIRECT)= 0;
//在下面這兩個函數后會介紹。它們的第二個參數表示使用的音頻流類型,
virtualstatus_t startOutput(audio_io_handle_t output,
AudioSystem::stream_type stream) = 0;
virtual status_t stopOutput(audio_io_handle_toutput,
AudioSystem::stream_type stream) = 0;
......
//音量控制:設置不同音頻流的音量級別范圍,例如MUSIC有15個級別的音量
virtual void initStreamVolume(AudioSystem::stream_type stream,
intindexMin,
intindexMax) = 0;
//設置某個音頻流類型的音量級,例如覺得music聲音太小時,可以調用這個函數提高音量級
virtualstatus_t setStreamVolumeIndex(AudioSystem::stream_type stream,
int index) = 0;
}
~~~
從上面的分析中可知,AudioPolicyInterface主要提供了一些設備切換管理和音量控制的接口。每個廠商都有各自的實現方式。目前,Audio系統提供了一個通用的實現類AudioPolicyManagerBase,以前這個類是放在hardware目錄下的,現在是放到framework目錄中了。圖7-12展示了AP和HAL類之間的關系:
:-: 
圖7-12 AudioPolicy和AudioPolicyInterface的關系
其中:
- AudioPolicyService有一個AudioPolicyInterface類型的對象。
- AudioPolicyManagerBase有一個AudioPolicyClientInterace的對象。
AudioPolicyInterface中的一些函數后面會分析到,這些函數中有很多參數都是以AudioSystem::xxx方式出現的,那么
AudioSystem又是什么呢?
3. AudioSystem的介紹
AudioSystem是一個Native類,這個類在Java層有對應的Java類,其中定義了一些重要的類型,比如音頻流流程、音頻設備等,這些都在AudioSystem.h中。下面來看其中的一些定義。
(1)stream type(音頻流類型)
音頻流類型,我們已在AudioTrack中見識過了,其完整定義如下:
~~~
enum stream_type {
DEFAULT =-1,//默認
VOICE_CALL = 0,//通話聲
SYSTEM = 1,//系統聲,例如開關機提示
RING = 2,//來電鈴聲
MUSIC = 3,//媒體播放聲
ALARM = 4,//鬧鐘等的警告聲
NOTIFICATION = 5,//短信等的提示聲
BLUETOOTH_SCO = 6,//藍牙SCO
ENFORCED_AUDIBLE = 7,//強制發聲,照相機的快門聲就屬于這個類型
DTMF = 8,//DTMF,撥號盤的按鍵聲
TTS = 9,//文本轉語音,Text to Speech
NUM_STREAM_TYPES
};
~~~
音頻流類型有什么用呢?為什么要做這種區分呢?它主要與兩項內容有關:
- 設備選擇:例如,之前在創建AudioTrack時,傳入的音頻流類型是MUSIC,當插上耳機時,這種類型的聲音只會從耳機中出來,但如果音頻流類型是RING,則會從耳機和揚聲器中同時出來。
- 音量控制:不同流類型音量級的個數不同,例如,MUSIC類型有15個級別可供用戶調節,而有些類型只有7個級別的音量。
(2)audio mode(聲音模式)
audio mode和電話的狀態有直接關系。先看它的定義:
~~~
enum audio_mode {
MODE_INVALID = -2,
MODE_CURRENT = -1,
MODE_NORMAL = 0, //正常,既不打電話,也沒有來電
MODE_RINGTONE,//有來電
MODE_IN_CALL,//通話狀態
NUM_MODES
};
~~~
為什么Audio需要特別強調Phone的狀態呢?這必須和智能手機的硬件架構聯系上。先看智能手機的硬件架構,如圖7-13所示:
:-: 
圖7-13 智能手機的硬件架構圖
從圖7-13中看出了什么?
- 系統有一個音頻DSP,聲音的輸入輸出都要經過它(不考慮藍牙的情況)。但它處理完的數字信號,需通過D/A(數/模)轉換后輸出到最終的設備上,這些設備包括揚聲器、聽筒、耳機等。
>[info] **注意**:所謂的設備切換,是指諸如揚聲器切換到聽筒的情況,而前面常提到的音頻輸出設備,應該指的是DSP。
- 系統有兩個核心處理器,一個是應用處理的核心,叫AP(Application Processor),可把它當做臺式機上的CPU,在這上面可以運行操作系統。另一個和手機通信相關,一般叫BP(Baseband Processor 基帶處理器),可把它當做臺式機上的“貓”。
- 從圖7-13中可看出,AP和BP都能向音頻DSP發送數據,它們在硬件上通路上互不干擾。于是就出現了一個問題,即如果兩個P同時往DSP發送數據,而互相之間沒有協調,就可能出現通話聲和音樂聲混雜的情況。誰還會用這樣的手機?所以打電話時,將由AP上的Phone程序主動設置Audio系統的mode,在這種mode下,Audio系統會做一些處理,例如把music音量調小等。
- 注意圖中的藍牙了嗎?它沒有像AP那樣直接和音頻DSP的相連,所以音頻數據需要單獨發給藍牙設備。如果某種聲音要同時從藍牙和揚聲器發出,亦即一份數據要往兩個地方發送,便滿足了AudioFlinger中DuplicatingThread出現的現實要求。
注意:藍牙設備實際上會建立兩條數據通路:SCO和A2DP。A2DP和高質量立體聲有關,且必須由AudioFlinger向它發送數據。所以“音頻數據需要單獨發送給藍牙設備”,這個設備實際上是指藍牙的A2DP設備。藍牙技術很復雜,有興趣的讀者可以自行研究。
(3)force use和config(強制使用及配置)
大家知道,手機通話時可以選擇揚聲器輸出,這就是強制使用的案例。Audio系統對此有很好的支持。它涉及到兩個方面:
- 強制使用何種設備,例如使用揚聲器、聽筒、耳機等。它由forced_config控制,代碼如下所示:
~~~
enum forced_config {
FORCE_NONE,
FORCE_SPEAKER, //強制使用揚聲器
FORCE_HEADPHONES,
FORCE_BT_SCO,
FORCE_BT_A2DP,
FORCE_WIRED_ACCESSORY,
FORCE_BT_CAR_DOCK,
FORCE_BT_DESK_DOCK,
NUM_FORCE_CONFIG,
FORCE_DEFAULT = FORCE_NONE
}
~~~
- 在什么情況下需要強制使用,是通話的強制使用,還是聽音樂的強制使用?這須由force_use控制,代碼如下所示:
~~~
enumforce_use {
FOR_COMMUNICATION,//通話情況,注意前綴,是FOR_XXX
FOR_MEDIA,//聽音樂等媒體相關的情況
FOR_RECORD,
FOR_DOCK,
NUM_FORCE_USE
}
~~~
所以,AudioPolicyInterface的setForceUse函數,就是設置在什么情況下強制使用什么設備:
~~~
virtual void setForceUse(AudioSystem::force_useusage,//什么情況
AudioSystem::forced_configconfig //什么設備
)= 0;
~~~
(4)輸出設備的定義
前面曾反復提到輸出設備。這些設備在軟件中是怎么表示的呢?Audio定義了很多輸出設備,來看其中幾個:
~~~
enum audio_devices {
//output devices
DEVICE_OUT_EARPIECE = 0x1, //聽筒
DEVICE_OUT_SPEAKER = 0x2, //揚聲器
DEVICE_OUT_WIRED_HEADSET = 0x4, //耳機
DEVICE_OUT_WIRED_HEADPHONE = 0x8, //另外一種耳機
DEVICE_OUT_BLUETOOTH_SCO = 0x10, //藍牙相關,SCO用于通話的語音傳輸
DEVICE_OUT_BLUETOOTH_SCO_HEADSET = 0x20,
DEVICE_OUT_BLUETOOTH_SCO_CARKIT= 0x40,
DEVICE_OUT_BLUETOOTH_A2DP = 0x80, //藍牙相關,A2DP用于立體聲傳輸
DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES = 0x100,
DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER = 0x200,
DEVICE_OUT_AUX_DIGITAL = 0x400,
DEVICE_OUT_DEFAULT= 0x8000,
......
}
~~~
至此,AudioSystem中常用的定義都已見過了,現在要回到APS的創建上了。對這個例子,將使用Generic的設備,所以會直接創建AudioPolicyManagerBase對象,這個對象實現了AudioPolicyInterface的所有功能。一起來看。
說明:實際上很多硬件廠商實現的AudioPolicyInterface,基本上是直接使用這個AudioPolicyManagerBase。
4. AudioPolicyManagerBase的分析
AudioPolicyManagerBase類在AudioPolicyManagerBase.cpp中實現,先來看它的構造函數:
**AudioPolicyManagerBase.cpp**
~~~
AudioPolicyManagerBase::AudioPolicyManagerBase(
AudioPolicyClientInterface*clientInterface)
:mPhoneState(AudioSystem::MODE_NORMAL),mRingerMode(0),
mMusicStopTime(0),mLimitRingtoneVolume(false)
{
//APS實現了AudioPolicyClientInterface接口
mpClientInterface= clientInterface;//這個clientInterface就是APS對象
//清空強制使用配置
for(int i = 0; i < AudioSystem::NUM_FORCE_USE; i++) {
mForceUse[i] = AudioSystem::FORCE_NONE;
}
//輸出設備有聽筒和揚聲器
mAvailableOutputDevices = AudioSystem::DEVICE_OUT_EARPIECE |
AudioSystem::DEVICE_OUT_SPEAKER;
//輸入設備是內置的麥克(學名叫傳聲器)
mAvailableInputDevices = AudioSystem::DEVICE_IN_BUILTIN_MIC;
#ifdef WITH_A2DP //和藍牙立體聲有關。
mA2dpOutput = 0;
mDuplicatedOutput = 0;
mA2dpDeviceAddress = String8("");
#endif
mScoDeviceAddress = String8(""); //SCO主要用于通話
/*
①創建一個AudioOutputDescriptor對象,這個對象用來記錄并維護與
輸出設備(相當于硬件的音頻DSP)相關的信息,例如使用該設備的流個數、各個流的音量、
該設備所支持的采樣率、采樣精度等。其中,有一個成員mDevice用來表示目前使用的輸出設備,
例如耳機、聽筒、揚聲器等
*/
AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor();
outputDesc->mDevice= (uint32_t)AudioSystem::DEVICE_OUT_SPEAKER;
/*
②還記得MixerThread的來歷嗎?openOutput導致AF創建了一個工作線程。
該函數返回的是一個工作線程索引號
*/
mHardwareOutput =mpClientInterface->openOutput(&outputDesc->mDevice,
&outputDesc->mSamplingRate,
&outputDesc->mFormat,
&outputDesc->mChannels,
&outputDesc->mLatency,
outputDesc->mFlags);
......
//AMB維護了一個與設備相關的key/value集合,下面將對應信息加到該集合中。
addOutput(mHardwareOutput,outputDesc);
//③設置輸出設備,就是設置DSP的數據流到底從什么設備出去,這里設置的是從揚聲器出去
setOutputDevice(mHardwareOutput,
(uint32_t)AudioSystem::DEVICE_OUT_SPEAKER,true);
}
//④更新不同策略使用的設備
updateDeviceForStrategy();
}
~~~
關于AMB這個小小的構造函數,有幾個重要點需要介紹:
(1)AudioOutputDescriptor和openOutput
AudioOutputDescriptor對象,是AMB用來控制和管理音頻輸出設備的,從硬件上看,它代表的是DSP設備。關于這一點已在注釋中做出說明,這里就不再贅述。
另一個重要點是openOutput函數。該函數的實現由APS來完成。之前曾分析過,它最終會在AF中創建一個混音線程(不考慮DirectOutput的情況),該函數返回的是該線程在AF中的索引號,亦即
~~~
mHardwareOutput =mpClientInterface->openOutput(......)
~~~
mHardwareOutput表示的是AF中一個混音線程的索引號。這里涉及到一個非常重要的設計問題:AudioFlinger到底會創建多少個MixerThread?有兩種設計方案:
- 一種是一個MixerThread對應一個Track。如果這樣,AMB僅使用一個mHardwareOutput恐怕還不夠用。
- 另一種是用一個MixerThread支持32路的Track數據,多路數據通過AudioMixer混音對象在軟件層面進行混音。
這里用的是第二種,當初設計時為何不用一個MixerThread支持一路Track,然后把混音的工作交給硬件來完成呢?我覺得,原因之一是如采用一個線程一個Track的方式,就非常難于管理和控制,另一個原因是多線程比較浪費資源。
如采用第二種方法(也就是現有的方案),就極大簡化了AMB的工作量。圖7-14展示了AMB和AF及MixerThread之間的關系:
:-: 
圖7-14 AF、AMB及MixerThread之間的關系
圖7-14表明:
- AMB中除了mHardwareOutput外,還有一個mA2dpOutput,它對應的MixerThread,專往代表藍牙A2DP設備的AudioStreamOut上發送數據。關于這個問題,在后面分析DuplicatingThread時可以見到。
* * * * *
**注意**:使用mA2dpOutput需要藍牙設備連接上才會有意義。
* * * * *
- 除了藍牙外,系統中一般也就只有圖7-14右邊這么一個MixerThread了,所以AMB通過mHardwareOutput就能控制整個系統的聲音,這真是一勞永逸。
* * * * *
**說明**:關于這一點,現在通過setOutputDevice來分析。
* * * * *
(2)setOutputDevice
現在要分析的調用是setOutputDevice,目的是為DSP選擇一個合適的輸出設備。注意它的第一個參數是傳入的mHardwareOutput,它最終會找到代表DSP的AudioStreamOut對象,第二個參數是一個設備號。
**AudioPolicyManagerBase.cpp**
~~~
void AudioPolicyManagerBase::setOutputDevice(audio_io_handle_toutput,
uint32_tdevice, bool force, int delayMs)
{
AudioOutputDescriptor*outputDesc = mOutputs.valueFor(output);
//判斷是否是Duplicate輸出,和藍牙A2DP有關,后面再做分析
if(outputDesc->isDuplicated()) {
setOutputDevice(outputDesc->mOutput1->mId, device, force,delayMs);
setOutputDevice(outputDesc->mOutput2->mId, device, force,delayMs);
return;
}
// 初始設置的輸出設備為聽筒和揚聲器
uint32_tprevDevice = (uint32_t)outputDesc->device();
if ((device == 0 || device == prevDevice)&& !force) {
return;
}
//現在設置新的輸出設備為揚聲器,注意這是軟件層面上的設置
outputDesc->mDevice = device;
......
/*
還需要硬件也做相應設置,主要是告訴DSP把它的輸出切換到某個設備上,根據之前的分析,
這個請求要發送到AF中的MixerThread上,因為只有它擁有代表輸出設備的AudioStreamOut
對象
*/
AudioParameter param = AudioParameter();
param.addInt(String8(AudioParameter::keyRouting),(int)device);
/*
上面的配置參數將投遞到APS的消息隊列,而APS中創建的AudioCommandThread
會取出這個配置參數,再投遞給AF中對應的MixerThread,最終由MixerThread處理。
這個流程,將在耳機插拔事件處理中進行分析
*/
mpClientInterface->setParameters(mHardwareOutput,
param.toString(),delayMs);
......
}
~~~
setOutputDevice要實現的目的已很明確,只是實現的過程比較繁瑣而已。其間沒有太多復雜之處,讀者可自行研究,以加深對Audio系統的了解。
(3)Audio Strategy
現調用的函數是updateDeviceForStrategy,這里會引出一個strategy的概念。先看updataDeviceForStrategy函數:
**AudioPolicyManagerBase.cpp**
~~~
voidAudioPolicyManagerBase::updateDeviceForStrategy()
{
for(int i = 0; i < NUM_STRATEGIES; i++) {
mDeviceForStrategy[i] =
getDeviceForStrategy((routing_strategy)i,false);
}
}
~~~
關于getDeviceForStrategy,在耳機插拔事件中再做分析,現在先看routing_stratgy的定義,代碼如下所示:
**getDeviceForStrategy.h::routing_strategy**
~~~
//routing_strategy:路由策略
enum routing_strategy {
STRATEGY_MEDIA,
STRATEGY_PHONE,
STRATEGY_SONIFICATION,
STRATEGY_DTMF,
NUM_STRATEGIES
}
~~~
它是在AudioPolicyManagerBase.h中定義的,一般的應用程序不會使用這個頭文件。這個routing_strategy有什么用處呢?從名字上看,似乎和路由的選擇有關系,但AudioSystem定義的是stream type,這兩者之間會有什么關系嗎?有,而且還很緊密。這個關系通過AMB的getStrategy就可以看出來。它會從指定的流類型得到對應的路由策略,代碼如下所示:
**AudioPolicyManagerBase.cpp**
~~~
AudioPolicyManagerBase::getStrategy(AudioSystem::stream_typestream)
{
switch(stream) {
caseAudioSystem::VOICE_CALL:
caseAudioSystem::BLUETOOTH_SCO:
return STRATEGY_PHONE; //PHONE路由策略
caseAudioSystem::RING:
caseAudioSystem::NOTIFICATION:
caseAudioSystem::ALARM:
caseAudioSystem::ENFORCED_AUDIBLE:
return STRATEGY_SONIFICATION; //SONIFICATION路由策略
caseAudioSystem::DTMF:
return STRATEGY_DTMF; //DTMF路由策略
default:
LOGE("unknown stream type");
caseAudioSystem::SYSTEM:
caseAudioSystem::TTS:
caseAudioSystem::MUSIC:
return STRATEGY_MEDIA;//media 路由策略
}
}
~~~
從這個函數中可看出,AudioSystem使用的流類型并不是和路由直接相關的,AMB或AudioPolicy內部,是使用routing_strategy來控制路由策略的。
5. 小結
這一節涉及到不少新東西,但本人覺得,最重要的還是圖7-13和圖7-14。其中:
- 圖7-13展示了智能手機的硬件架構,通過和Audio相關的架構設計,我們能理解Audio系統設計的緣由。
- 圖7-14展示了APS和AF內部聯系的紐帶,后續APS的控制無非就是找到對應的MixerThread,給它發送控制消息,最終由MixerThread將控制信息傳給對應的代表音頻輸出設備的HAL對象。
- 前言
- 第1章 閱讀前的準備工作
- 1.1 系統架構
- 1.1.1 Android系統架構
- 1.1.2 本書的架構
- 1.2 搭建開發環境
- 1.2.1 下載源碼
- 1.2.2 編譯源碼
- 1.3 工具介紹
- 1.3.1 Source Insight介紹
- 1.3.2 Busybox的使用
- 1.4 本章小結
- 第2章 深入理解JNI
- 2.1 JNI概述
- 2.2 學習JNI的實例:MediaScanner
- 2.3 Java層的MediaScanner分析
- 2.3.1 加載JNI庫
- 2.3.2 Java的native函數和總結
- 2.4 JNI層MediaScanner的分析
- 2.4.1 注冊JNI函數
- 2.4.2 數據類型轉換
- 2.4.3 JNIEnv介紹
- 2.4.4 通過JNIEnv操作jobject
- 2.4.5 jstring介紹
- 2.4.6 JNI類型簽名介紹
- 2.4.7 垃圾回收
- 2.4.8 JNI中的異常處理
- 2.5 本章小結
- 第3章 深入理解init
- 3.1 概述
- 3.2 init分析
- 3.2.1 解析配置文件
- 3.2.2 解析service
- 3.2.3 init控制service
- 3.2.4 屬性服務
- 3.3 本章小結
- 第4章 深入理解zygote
- 4.1 概述
- 4.2 zygote分析
- 4.2.1 AppRuntime分析
- 4.2.2 Welcome to Java World
- 4.2.3 關于zygote的總結
- 4.3 SystemServer分析
- 4.3.1 SystemServer的誕生
- 4.3.2 SystemServer的重要使命
- 4.3.3 關于 SystemServer的總結
- 4.4 zygote的分裂
- 4.4.1 ActivityManagerService發送請求
- 4.4.2 有求必應之響應請求
- 4.4.3 關于zygote分裂的總結
- 4.5 拓展思考
- 4.5.1 虛擬機heapsize的限制
- 4.5.2 開機速度優化
- 4.5.3 Watchdog分析
- 4.6 本章小結
- 第5章 深入理解常見類
- 5.1 概述
- 5.2 以“三板斧”揭秘RefBase、sp和wp
- 5.2.1 第一板斧--初識影子對象
- 5.2.2 第二板斧--由弱生強
- 5.2.3 第三板斧--破解生死魔咒
- 5.2.4 輕量級的引用計數控制類LightRefBase
- 5.2.5 題外話-三板斧的來歷
- 5.3 Thread類及常用同步類分析
- 5.3.1 一個變量引發的思考
- 5.3.2 常用同步類
- 5.4 Looper和Handler類分析
- 5.4.1 Looper類分析
- 5.4.2 Handler分析
- 5.4.3 Looper和Handler的同步關系
- 5.4.4 HandlerThread介紹
- 5.5 本章小結
- 第6章 深入理解Binder
- 6.1 概述
- 6.2 庖丁解MediaServer
- 6.2.1 MediaServer的入口函數
- 6.2.2 獨一無二的ProcessState
- 6.2.3 時空穿越魔術-defaultServiceManager
- 6.2.4 注冊MediaPlayerService
- 6.2.5 秋風掃落葉-StartThread Pool和join Thread Pool分析
- 6.2.6 你徹底明白了嗎
- 6.3 服務總管ServiceManager
- 6.3.1 ServiceManager的原理
- 6.3.2 服務的注冊
- 6.3.3 ServiceManager存在的意義
- 6.4 MediaPlayerService和它的Client
- 6.4.1 查詢ServiceManager
- 6.4.2 子承父業
- 6.5 拓展思考
- 6.5.1 Binder和線程的關系
- 6.5.2 有人情味的訃告
- 6.5.3 匿名Service
- 6.6 學以致用
- 6.6.1 純Native的Service
- 6.6.2 扶得起的“阿斗”(aidl)
- 6.7 本章小結
- 第7章 深入理解Audio系統
- 7.1 概述
- 7.2 AudioTrack的破解
- 7.2.1 用例介紹
- 7.2.2 AudioTrack(Java空間)分析
- 7.2.3 AudioTrack(Native空間)分析
- 7.2.4 關于AudioTrack的總結
- 7.3 AudioFlinger的破解
- 7.3.1 AudioFlinger的誕生
- 7.3.2 通過流程分析AudioFlinger
- 7.3.3 audio_track_cblk_t分析
- 7.3.4 關于AudioFlinger的總結
- 7.4 AudioPolicyService的破解
- 7.4.1 AudioPolicyService的創建
- 7.4.2 重回AudioTrack
- 7.4.3 聲音路由切換實例分析
- 7.4.4 關于AudioPolicy的總結
- 7.5 拓展思考
- 7.5.1 DuplicatingThread破解
- 7.5.2 題外話
- 7.6 本章小結
- 第8章 深入理解Surface系統
- 8.1 概述
- 8.2 一個Activity的顯示
- 8.2.1 Activity的創建
- 8.2.2 Activity的UI繪制
- 8.2.3 關于Activity的總結
- 8.3 初識Surface
- 8.3.1 和Surface有關的流程總結
- 8.3.2 Surface之乾坤大挪移
- 8.3.3 乾坤大挪移的JNI層分析
- 8.3.4 Surface和畫圖
- 8.3.5 初識Surface小結
- 8.4 深入分析Surface
- 8.4.1 與Surface相關的基礎知識介紹
- 8.4.2 SurfaceComposerClient分析
- 8.4.3 SurfaceControl分析
- 8.4.4 writeToParcel和Surface對象的創建
- 8.4.5 lockCanvas和unlockCanvasAndPost分析
- 8.4.6 GraphicBuffer介紹
- 8.4.7 深入分析Surface的總結
- 8.5 SurfaceFlinger分析
- 8.5.1 SurfaceFlinger的誕生
- 8.5.2 SF工作線程分析
- 8.5.3 Transaction分析
- 8.5.4 關于SurfaceFlinger的總結
- 8.6 拓展思考
- 8.6.1 Surface系統的CB對象分析
- 8.6.2 ViewRoot的你問我答
- 8.6.3 LayerBuffer分析
- 8.7 本章小結
- 第9章 深入理解Vold和Rild
- 9.1 概述
- 9.2 Vold的原理與機制分析
- 9.2.1 Netlink和Uevent介紹
- 9.2.2 初識Vold
- 9.2.3 NetlinkManager模塊分析
- 9.2.4 VolumeManager模塊分析
- 9.2.5 CommandListener模塊分析
- 9.2.6 Vold實例分析
- 9.2.7 關于Vold的總結
- 9.3 Rild的原理與機制分析
- 9.3.1 初識Rild
- 9.3.2 RIL_startEventLoop分析
- 9.3.3 RIL_Init分析
- 9.3.4 RIL_register分析
- 9.3.5 關于Rild main函數的總結
- 9.3.6 Rild實例分析
- 9.3.7 關于Rild的總結
- 9.4 拓展思考
- 9.4.1 嵌入式系統的存儲知識介紹
- 9.4.2 Rild和Phone的改進探討
- 9.5 本章小結
- 第10章 深入理解MediaScanner
- 10.1 概述
- 10.2 android.process.media分析
- 10.2.1 MSR模塊分析
- 10.2.2 MSS模塊分析
- 10.2.3 android.process.media媒體掃描工作的流程總結
- 10.3 MediaScanner分析
- 10.3.1 Java層分析
- 10.3.2 JNI層分析
- 10.3.3 PVMediaScanner分析
- 10.3.4 關于MediaScanner的總結
- 10.4 拓展思考
- 10.4.1 MediaScannerConnection介紹
- 10.4.2 我問你答
- 10.5 本章小結