我是靠谱客的博主 俊秀冬瓜,最近开发中收集的这篇文章主要介绍【Android Audio】onAudioPortListUpdate 和 onAudioPatchListUpdate回调流程,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

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回调流程所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(55)

评论列表共有 0 条评论

立即
投稿
返回
顶部