欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android耳機(jī)插拔檢測(framework篇)原理解析

 更新時間:2024年11月26日 10:56:12   作者:呦呦呦是代碼啊  
文章詳細(xì)介紹了Android系統(tǒng)中音頻設(shè)備插拔事件的處理流程,包括事件的獲取、處理和上報,本文給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧

基本原理
在輸入設(shè)備驅(qū)動(input_dev)中,一般通過輪詢或者中斷方式獲取輸入事件的原始值(raw value),經(jīng)過處理后再使用input_evnet()函數(shù)上報;
android native層的input flinger會去讀這個event,讀到后往android java層notify,notify給InputManagerService/WiredAccessoryManager,WiredAccessoryManager在處理這個msg。
涉及到的類文件:
● InputManagerService.java
./framework/base/services/core/java/com/android/server/input/InputManagerService.java
*WiredAccessoryManager.java.
./framework/base/services/core/java/com/android/server/WiredAccessoryManager.java
config.xml
./framework/base/core/res/res/values/config.xml
SystemServer.java
./framework/base/services/java/com/android/server/SystemServer.java
AudioManager.java
./base/media/java/android/media/AudioManager.java
AudioService.java
./base/media/java/android/media/AudioService.java

InputReader.cpp->InputReader::processEventsLocked()
InputDevice.cpp->InputDevice:process()
SwitchInputMapper.cpp->SwitchInputMapper::process()
InputMapper.h->InputMap::getListener()
InputListener.cpp->mQueuedListener->notifySwitch

3)傳遞事件
InputListener.cpp->QueuedInputListener::flush()
NotifySwitchArgs::notify
InputClassifier::notifySwitch
InputDispatcher.cpp->InputDispatcher::notifySwitch()
com_android_server_input_InputManagerService.cpp->NativeInputManager::notifySwitch()
InputManagerService.java->InputManagerService::notifySwitch()
WiredAccessoryManager.java->WiredAccessoryManager::notifyWiredAccessoryChanged()
WiredAccessoryManager.java->WiredAccessoryManager::updateLocked()
WiredAccessoryManager.java->WiredAccessoryManager::setDeviceStateLocked
AUdioManager.java->AudioManager::setWiredDeviceConnectionState()
AudioService.java->AudioSystem::setWiredDeviceConnectionState()
AudioDeviceInventory->AudioDeviceInventory::onSetWiredDeviceConnectionState()

a)AudioDeviceInventory::handleDeviceConnection()
AudioDeviceInventory.java->AudioDeviceInventory::handleDeviceConnection()
AudioSystem.cpp->AudioSystem::setDeviceConnectionState()
AudioPolicyManager.cpp->AudioPolicyManager::setDeviceConnectionState()
class AudioPolicyClientInterface:
AudioPolicyService.cpp->AudioPolicyService:: SET_PARAMETERS
AudioFlinger.cpp->AudioFlinger::setParameters()
DeviceHalHidl.cpp->DeviceHalHidl::setParameters()
Device.cpp->Device::halSetParameters()
audio_hw.c->audio_hal::adev_set_parameters()

b) sendDeviceConnectionIntent()

c)updateAudioRoutes()
AudioDeviceBroker.java->postReportNewRoutes()
AudioDeviceInventory.java->onReportNewRoute()
MediaRouter.java->dispatchAudioRoutesChanged()
MediaRouter.java->updateAduioRoutes()

二 插拔事件上報

2.1 支持的設(shè)備類型
當(dāng)前支持的具體外設(shè)設(shè)備如下:
![在這里插入圖片描述](https://i-blog.csdnimg.cn/direct/1ffbd9aa88f343068239c77713363d02.png

2.2 上報方式

有兩種上報插拔事件的方式,一種是輸入子系統(tǒng),另外一種uevent事件上報。

輸入子系統(tǒng)(InputEvent):可以上報按鍵事件也可以上報開關(guān)事件,事件類型包括headset\headPhone\Lineout。對于輸入設(shè)備都需要指定能產(chǎn)生同步類EV_SYN;switch class子系統(tǒng),通過uevent向用戶空間發(fā)送數(shù)據(jù),Android中有個線程專門監(jiān)聽此類事件。使用switch dev子系統(tǒng)時,名字必須要設(shè)置為"h2w",Android系統(tǒng)監(jiān)聽 /sys/class/switch/h2s這個虛擬設(shè)備。
Android系統(tǒng)中最終使用哪種方式?
可以通過配置Android系統(tǒng)中配置文件:在Android系統(tǒng)中默認(rèn)是使用UEvent的方式。不過一般廠商會在自己的xml文件中進(jìn)行配置。
frameworks/base/core/res/res/values/config.xml或者是device/eswin/common/overlay/frameworks/base/core/res/res/values/config.xml
第二個文件會覆蓋第一個文件,修改文件中的**true**變量,該值為true時使用的是tvinput子系統(tǒng),false為ueven機(jī)制。
在InputManagerService.java的構(gòu)造函數(shù)中,config_useDevInputEventForAudioJack的值的初始化mUseDevInputEventForAudioJack決定采用那種方式。所以最終采用的是tvinput子系統(tǒng)的方式。
路徑:frameworks/base/services/core/java/com/android/server/input/InputManagerService.java

三 代碼流程

第一個階段 事件信息上報

input子系統(tǒng)通過inputReader開始讀取事件并處理。(記住這里的InputLisenerInterface listener)
路徑:/frameworks/native/services/inputflinger/reader/InputReader.cpp
InputRead構(gòu)造函數(shù)如下:

對于InputReadThread:
1)啟動循環(huán)后執(zhí)行mReader->loopOnce(),loopOnce()中會調(diào)用mEventHub→getEvents讀取事件;
2)調(diào)用processEventsLocked()處理事件;
3)調(diào)用mPolicy->notifyInputDeviceChanged()用InputManagerService的代理通過Handler發(fā)送MSG_DELIVER_INPUT_DEVICES_CHANGED消息,通知輸入設(shè)備發(fā)生了變化;
4)調(diào)用mQueuedListener->flush(),將事件隊列中的所有事件交給在InputReader中注冊過的InputDispatcher

獲取事件;2)處理事件;3)傳遞事件

1)獲取事件

size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE)主要是從DEVICE_PATH = /dev/input獲取kernel的event,這里的事件不僅包含了input,也包含了輸入設(shè)備的add/remove。
(后續(xù)補(bǔ)充)
2)處理事件

通過getEvents()函數(shù)從驅(qū)動中獲取到事件后,調(diào)用processEventsLocked()函數(shù)開始處理:
InputReader.cpp->InputReader::processEventsLocked()
路徑:***

根據(jù)不同的deviceIdc從mDevice中獲取到對應(yīng)的Device,獲取到Device后,判斷該Device是否合法以及是否需要被忽略,如果不是,接下來需要調(diào)用deivce->process()進(jìn)行事件處理。
InputDevice,cpp->InputDevice:process()
路徑:frameworks/native/services/inputflinger/reader/InputDevice.cpp

該函數(shù)中,會依次處理同一個device產(chǎn)生的普通輸入事件,然后通過for_each_mapper_in_subdevice()進(jìn)行轉(zhuǎn)換調(diào)用InputMapper.process()進(jìn)行事件處理。
for_each_mapper_in_subdevice:

路徑:frameworks/native/services/inputflinger/reader/mapper/
從該路徑下的mapper類可以看出,Android將輸入設(shè)備分為以下幾種類型:
● CursorInputMapper :鼠標(biāo)
ExternalStylusInputMapper : 觸控筆
JoystickInputMapper :游戲桿
KeyboardInputMapper :鍵盤
KeyMouseInputMapper :通常由一個手持設(shè)備組成,具有鍵盤和觸控板/鼠標(biāo)的功能,適用于需要鍵盤輸入和鼠標(biāo)操作的情況,如在移動設(shè)備上進(jìn)行文字輸入和瀏覽。
RotaryEncoderInputMapper :旋轉(zhuǎn)編碼器輸入設(shè)備,一種用于測量旋轉(zhuǎn)運(yùn)動的設(shè)備。
SwitchInputMapper : 開關(guān)
TouchInputMapper 、MultiTouchInputMapper、SingleTouchInputMapper:觸摸屏
VibratorInputMapper :震動器,嚴(yán)格意義上是輸出設(shè)備
SwitchInputMapper.cpp->SwitchInputMapper::process()
路徑:frameworks/native/services/inputflinger/reader/mapper/SwitchInputMapper.cpp

將所有的事件信息封裝成一個NotifySwitchArgs對象。所以這個getLintener()是誰??
InputMapper.h->InputMap::getListener()
路徑:frameworks/native/services/inputflinger/reader/mapper/InputMapper.h

而mDeviceContext又是一個InputDeviceContext類型的,可以看到:
inline InputReaderContext* getContext() { return mContext; } 實(shí)際上調(diào)用是InputReadContext中的getListener()函數(shù)
路徑:frameworks\native\services\inputflinger\reader\InputReader.cpp
InputListenerInterface* InputReader::ContextImpl::getListener() {
return mReader->mQueuedListener.get();
}
所以getListener()->notifySwtch最終為mQueuedListener->notifySwitch(&args)
InputListener.cpp->mQueuedListener->notifySwitch
路徑:frameworks/native/services/inputflinger/InputListener.cpp

最終將相關(guān)事件信息存放到mArgsQueue隊列中。
3)傳遞事件

InputListener.cpp->QueuedInputListener::flush()
路徑:frameworks\native\services\inputflinger\InputListener.cpp

在flush()函數(shù)中,依次取出mArgsQueue隊列中的數(shù)據(jù),調(diào)用NotifyArgs args->notify(mInnerListener)進(jìn)行處理。
NotifySwitchArgs::notify
void NotifySwitchArgs::notify(const sp& listener) const { listener->notifySwitch(this); }
調(diào)用的是 listener->notifySwitch(this), 所有傳入的mInnerListener是哪位??
路徑:frameworks\native\services\inputflinger\InputListener.cpp
QueuedInputListener::QueuedInputListener(const sp& innerListener) : mInnerListener(innerListener) { }

InputManager::InputManager()
路徑:frameworks/native/services/inputflinger/InputManager.cpp

所以上面的mInnerListener就是mClassifier,調(diào)用的是mClassifier→notifySwitch()
InputClassifier::notifySwitch
void InputClassifier::notifySwitch(const NotifySwitchArgs* args) {
// pass through
mListener->notifySwitch(args);
}
構(gòu)造函數(shù):
InputClassifier::InputClassifier(const sp& listener) : mListener(listener), mHalDeathRecipient(new HalDeathRecipient(*this)) {}
可以觀察到,mListener(listener)還是上面帶下來的參數(shù)InputDispatcher::mDispatcher,也就是mClassifier→notifySwitch()最終調(diào)用的是InputDispatcher::notifySwitch()
InputDispatcher.cpp->InputDispatcher::notifySwitch()
路徑:frameworks\native\services\inputflinger\dispatcher\InputDispatcher.cpp

構(gòu)造函數(shù):

可以觀察在InputDispatcherPolicyInterface中是個虛函數(shù),最終實(shí)現(xiàn)在NativeInputManager::notifySwitch()
com_android_server_input_InputManagerService.cpp->NativeInputManager::notifySwitch()
路徑:frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp

路徑:frameworks/base/services/core/java/com/android/server/input/InputManagerService.java

全局搜索下同名函數(shù)“notifySwitch”
InputManagerService.java->InputManagerService::notifySwitch()
路徑:frameworks\base\services\core\java\com\android\server\input\InputManagerService.java

根據(jù)從xml中獲取到的mUseDevInputEventForAudioJack = true,進(jìn)入到

WiredAccessoryManager.java->WiredAccessoryManager::notifyWiredAccessoryChanged()
路徑:frameworks/base/services/core/java/com/android/server/WiredAccessoryManager.java

WiredAccessoryManager.java->WiredAccessoryManager::updateLocked()
更新耳機(jī)狀態(tài),這里又分了多種耳機(jī): usb_headset_anlg、usb_headset_dgtl 、h2w_headset

設(shè)置outputDevice = DEVICE_OUT_WIRED_HEADPHONE = 0x8
WiredAccessoryManager.java->WiredAccessoryManager::setDeviceStateLocked
路徑:frameworks\base\services\core\java\com\android\server\WiredAccessoryManager.java

判斷headphone是否帶mic。
AUdioManager.java->AudioManager::setWiredDeviceConnectionState()
路徑:frameworks/base/media/java/android/media/AudioManager.java

(涉及到Binder通信一堆東西)
AudioService.java->AudioSystem::setWiredDeviceConnectionState()
路徑:frameworks/base/services/core/java/com/android/server/audio/AudioService.java

圍繞著:
frameworks/base/services/core/java/com/android/server/audio/AudioDeviceBroker.java
frameworks/base/services/core/java/com/android/server/audio/AudioDeviceInventory.java
AudioDeviceBroker::setWiredDeviceConnectionState()
->AudioDeviceInventory::setWiredDeviceConnectionState()
→AudioDeviceBroker::postSetWiredDeviceConnectionState()
→AudioDeviceInventory::onSetWiredDeviceConnectionState()
AudioDeviceInventory->AudioDeviceInventory::onSetWiredDeviceConnectionState()

該函數(shù)主要分為三步:
a)handleDeviceConnection() 確保設(shè)備連接并向下設(shè)置設(shè)備支持的參數(shù);
b)sendDeviceConnectionIntent() 向上發(fā)送設(shè)備狀態(tài)
c) updataAudioRoutes() 更新Audio路由
a)AudioDeviceInventory::handleDeviceConnection()
AudioDeviceInventory.java->AudioDeviceInventory::handleDeviceConnection()
路徑:frameworks\base\services\core\java\com\android\server\audio\AudioDeviceInventory.java

如果設(shè)備已經(jīng)連接了
通過final int res = mAudioSystem.setDeviceConnectionState(device, AudioSystem.DEVICE_STATE_AVAILABLE, address, deviceName, AudioSystem.AUDIO_FORMAT_DEFAULT);
通過AudioSystemAdapter.java->AudioSystem.java->android_media_AudioSystem.cpp->AudioSystem.cpp
AudioSystem.cpp->AudioSystem::setDeviceConnectionState()
路徑:frameworks/av/media/libaudioclient/AudioSystem.cpp

AudioPolicyManager.cpp->AudioPolicyManager::setDeviceConnectionState()
路徑:frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
→AudioPolicyManager::setDeviceConnectionStateInt()
路徑:frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp

先看這個**broadcastDeviceConnectionState(dev, state);**通過調(diào)用setParameters()通知所有的hardware module,有新的設(shè)備正在處理中:

class AudioPolicyClientInterface:
路徑:frameworks/av/services/audiopolicy/AudioPolicyInterface.h

AudioPolicyClientInterface實(shí)現(xiàn)在AudioPolicyClientImpl.cpp中,調(diào)用到AudioPolicyService中:
AudioPolicyService.cpp->AudioPolicyService:: SET_PARAMETERS
路徑:frameworks/av/services/audiopolicy/service/AudioPolicyService.cpp

AudioFlinger.cpp->AudioFlinger::setParameters()
路徑:frameworks/av/services/audioflinger/AudioFlinger.cpp

DeviceHalHidl.cpp->DeviceHalHidl::setParameters()
路徑:frameworks/av/media/libaudiohal/impl/DeviceHalHidl.cpp

Device.cpp->Device::halSetParameters()
路徑:hardware/interfaces/audio/core/all-versions/default/Device.cpp

audio_hw.c->audio_hal::adev_set_parameters()

b) sendDeviceConnectionIntent()
發(fā)送intent去通知音頻外設(shè)的狀態(tài)變化。
路徑:frameworks/base/services/core/java/com/android/server/audio/AudioDeviceInventory.java

c)updateAudioRoutes()
更新音頻路徑
路徑:frameworks/base/services/core/java/com/android/server/audio/AudioDeviceInventory.java
根據(jù)不同的device設(shè)置connType并和前一次的mainType進(jìn)行比較是否需要更新route

AudioDeviceBroker.java->postReportNewRoutes()
/package/ void postReportNewRoutes(boolean fromA2dp) {
sendMsgNoDelay(fromA2dp ? MSG_REPORT_NEW_ROUTES_A2DP : MSG_REPORT_NEW_ROUTES, SENDMSG_NOOP);
}
handleMessage()
case MSG_REPORT_NEW_ROUTES:
case MSG_REPORT_NEW_ROUTES_A2DP:
synchronized (mDeviceStateLock) {
mDeviceInventory.onReportNewRoutes();
}
break;
(搞不懂這里,MSG_REPORT_NEW_ROUTES和MSG_REPORT_NEW_ROUTES_A2DP處理流程走到一樣,還區(qū)分兩者)
AudioDeviceInventory.java->onReportNewRoute()
路徑:frameworks\base\services\core\java\com\android\server\audio\AudioDeviceInventory.java

MediaRouter.java->dispatchAudioRoutesChanged()

其中的mIsBluetoothA2dpOn = mAudioService.isBluetoothA2dpOn()獲取當(dāng)前BT設(shè)備的狀態(tài),會調(diào)用到AudioDeviceBroker.java->isBluetoothA2dpOn()

MediaRouter.java->updateAduioRoutes()
判斷路由信息是否發(fā)生了改變。

到此這篇關(guān)于Android耳機(jī)插拔檢測(framework篇)原理解析的文章就介紹到這了,更多相關(guān)Android耳機(jī)插拔檢測內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論