概述
onAudioPortListUpdate 和 onAudioPatchListUpdate回调流程)
- 1、onAudioPortListUpdate
- 2、onAudioPatchListUpdate
- 3、注册流程
- 4、回调流程
先上图
1、onAudioPortListUpdate
当系统的output和input发生变化、output device和input device发生变化时都会触发该函数的调用
2、onAudioPatchListUpdate
当系统的audio patch发生变化,切换、新增、删除时都会触发该函数的调用
3、注册流程
1、注册回调类
以TvInputHardwareManager.java中注册回调函数为例:
mAudioManager.registerAudioPortUpdateListener(mAudioListener);
private final AudioManager.OnAudioPortUpdateListener mAudioListener =
new AudioManager.OnAudioPortUpdateListener() {
@Override
public void onAudioPortListUpdate(AudioPort[] portList) {
synchronized (mImplLock) {
updateAudioConfigLocked();
}
}
@Override
public void onAudioPatchListUpdate(AudioPatch[] patchList) {
// No-op
}
@Override
public void onServiceDied() {
}
};
2、通过AudioManager.registerAudioPortUpdateListener接口注册,
@UnsupportedAppUsage
public void registerAudioPortUpdateListener(OnAudioPortUpdateListener l) {
sAudioPortEventHandler.init();
sAudioPortEventHandler.registerListener(l);
}
3、AudioManager中有个静态成员AudioPortEventHandler sAudioPortEventHandler,保证每个进程只会有一个AudioPortEventHandler 实例;
AudioPortEventHandler.java
private static final AudioPortEventHandler sAudioPortEventHandler = new AudioPortEventHandler();
4、每个进程第一次注册时会触发init函数的调用,创建一个消息处理线程handler,将callback实例放到mListeners。同一进程第二次注册时不再重新创建,而是将callback实例放到AudioPortEventHandler的mListeners列表中保存
void registerListener(AudioManager.OnAudioPortUpdateListener l) {
synchronized (mLock) {
mListeners.add(l);
}
if (mHandler != null) {
Message m = mHandler.obtainMessage(AUDIOPORT_EVENT_NEW_LISTENER, 0, 0, l);
mHandler.sendMessage(m);
}
}
frameworksbasecorejniandroid_media_AudioSystem.cpp
5、第一次创建mHandler时会通过native_setup调用JNI的android_media_AudioSystem_eventHandlerSetup函数,
void init() {
...
mHandler = new Handler(mHandlerThread.getLooper()) {
...
};
native_setup(new WeakReference<AudioPortEventHandler>(this));
...
}
6、将AudioPortEventHandler实例再次封装成C++层的JNIAudioPortCallback实例,通过AudioSystem::addAudioPortCallback注册
static void
android_media_AudioSystem_eventHandlerSetup(JNIEnv *env, jobject thiz, jobject weak_this)
{
sp<JNIAudioPortCallback> callback = new JNIAudioPortCallback(env, thiz, weak_this);
if (AudioSystem::addAudioPortCallback(callback) == NO_ERROR) {
setJniCallback(env, thiz, callback);
}
}
status_t AudioSystem::addAudioPortCallback(const sp<AudioPortCallback>& callback)
{
...
int ret = gAudioPolicyServiceClient->addAudioPortCallback(callback);
...
return (ret < 0) ? INVALID_OPERATION : NO_ERROR;
}
7、最后AudioSystem::AudioPolicyServiceClient的mAudioPortCallbacks容器中保存每一个注册的JNIAudioPortCallback实例
int AudioSystem::AudioPolicyServiceClient::addAudioPortCallback(
const sp<AudioPortCallback>& callback)
{
Mutex::Autolock _l(mLock);
for (size_t i = 0; i < mAudioPortCallbacks.size(); i++) {
if (mAudioPortCallbacks[i] == callback) {
return -1;
}
}
mAudioPortCallbacks.add(callback);
return mAudioPortCallbacks.size();
}
4、回调流程
1、每个进程第一次使用AudioSystem接口时,在拿取get_audio_policy_service时会通过AudioPolicyService::registerClient()接口注册一个AudioPolicyServiceClient实例,这样每个进程的实例就注册到服务端的audioserver的mNotificationClients容器中了
const sp<IAudioPolicyService> AudioSystem::get_audio_policy_service()
{
...
if (gAudioPolicyServiceClient == NULL) {
gAudioPolicyServiceClient = new AudioPolicyServiceClient();
}
...
apc = gAudioPolicyServiceClient;
...
int64_t token = IPCThreadState::self()->clearCallingIdentity();
ap->registerClient(apc);
...
return ap;
}
void AudioPolicyService::registerClient(const sp<IAudioPolicyServiceClient>& client)
{
...
if (mNotificationClients.indexOfKey(token) < 0) {
sp<NotificationClient> notificationClient = new NotificationClient(this,client,uid,pid);
mNotificationClients.add(token, notificationClient);
...
}
回调开始
以设备断开和连接触发onAudioPortListUpdate为例,setDeviceConnectionStateInt每次会触发
status_t AudioPolicyManager::setDeviceConnectionStateInt(const sp<DeviceDescriptor> &device,
audio_policy_dev_state_t state)
{
...
mpClientInterface->onAudioPortListUpdate();
...
}
frameworksavservicesaudiopolicyserviceAudioPolicyClientImpl.cpp
void AudioPolicyService::AudioPolicyClient::onAudioPortListUpdate()
{
mAudioPolicyService->onAudioPortListUpdate();
}
frameworksavservicesaudiopolicyserviceAudioPolicyService.cpp
void AudioPolicyService::onAudioPortListUpdate()
{
mOutputCommandThread->updateAudioPortListCommand();
}
void AudioPolicyService::AudioCommandThread::updateAudioPortListCommand()
{
sp<AudioCommand> command = new AudioCommand();
command->mCommand = UPDATE_AUDIOPORT_LIST;
sendCommand(command);
}
bool AudioPolicyService::AudioCommandThread::threadLoop()
{
...
case UPDATE_AUDIOPORT_LIST: {
ALOGI("[%s:%d] ", __func__, __LINE__);
svc = mService.promote();
if (svc == 0) {
break;
}
mLock.unlock();
svc->doOnAudioPortListUpdate();
mLock.lock();
}break;
...
}
mNotificationClients根据各个进程的client进行回调
void AudioPolicyService::doOnAudioPortListUpdate()
{
Mutex::Autolock _l(mNotificationClientsLock);
for (size_t i = 0; i < mNotificationClients.size(); i++) {
mNotificationClients.valueAt(i)->onAudioPortListUpdate();
}
}
void AudioPolicyService::NotificationClient::onAudioPortListUpdate()
{
if (mAudioPolicyServiceClient != 0 && mAudioPortCallbacksEnabled) {
mAudioPolicyServiceClient->onAudioPortListUpdate();
}
}
最后回调到客户端进程,mAudioPortCallbacks就是多个JNIAudioPortCallback实例
void AudioSystem::AudioPolicyServiceClient::onAudioPortListUpdate()
{
Mutex::Autolock _l(mLock);
for (size_t i = 0; i < mAudioPortCallbacks.size(); i++) {
mAudioPortCallbacks[i]->onAudioPortListUpdate();
}
}
回调各个客户的的AudioPortEventHandler的postEventFromNative函数
void JNIAudioPortCallback::onAudioPortListUpdate()
{
sendEvent(AUDIOPORT_EVENT_PORT_LIST_UPDATED);
}
void JNIAudioPortCallback::sendEvent(int event)
{
JNIEnv *env = AndroidRuntime::getJNIEnv();
if (env == NULL) {
return;
}
env->CallStaticVoidMethod(mClass, gAudioPortEventHandlerMethods.postEventFromNative, mObject,
event, 0, 0, NULL);
if (env->ExceptionCheck()) {
ALOGW("An exception occurred while notifying an event.");
env->ExceptionClear();
}
}
最后调用到java层,发送AUDIOPORT_EVENT_PORT_LIST_UPDATED更新消息给mHandler线程,
@UnsupportedAppUsage
private static void postEventFromNative(Object module_ref,
int what, int arg1, int arg2, Object obj) {
AudioPortEventHandler eventHandler =
(AudioPortEventHandler)((WeakReference)module_ref).get();
if (eventHandler == null) {
return;
}
if (eventHandler != null) {
Handler handler = eventHandler.handler();
if (handler != null) {
Message m = handler.obtainMessage(what, arg1, arg2, obj);
if (what != AUDIOPORT_EVENT_NEW_LISTENER) {
// Except AUDIOPORT_EVENT_NEW_LISTENER, we can only respect the last message.
handler.removeMessages(what);
}
handler.sendMessage(m);
}
}
}
mHandler线程处理消息AUDIOPORT_EVENT_PORT_LIST_UPDATED
switch (msg.what) {
case AUDIOPORT_EVENT_NEW_LISTENER:
case AUDIOPORT_EVENT_PORT_LIST_UPDATED:
AudioPort[] portList = ports.toArray(new AudioPort[0]);
for (int i = 0; i < listeners.size(); i++) {
listeners.get(i).onAudioPortListUpdate(portList);
}
if (msg.what == AUDIOPORT_EVENT_PORT_LIST_UPDATED) {
break;
}
// FALL THROUGH
case AUDIOPORT_EVENT_PATCH_LIST_UPDATED:
AudioPatch[] patchList = patches.toArray(new AudioPatch[0]);
for (int i = 0; i < listeners.size(); i++) {
listeners.get(i).onAudioPatchListUpdate(patchList);
}
break;
frameworksbaseservicescorejavacomandroidservertvTvInputHardwareManager.java
通过listeners调用到TvInputHardwareManager.java的mAudioListener的onAudioPortListUpdate函数。
最后
以上就是俊秀冬瓜为你收集整理的【Android Audio】onAudioPortListUpdate 和 onAudioPatchListUpdate回调流程的全部内容,希望文章能够帮你解决【Android Audio】onAudioPortListUpdate 和 onAudioPatchListUpdate回调流程所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复