Android Audio系列 AudioPatch的bug

来源:互联网 发布:淘宝澳洲站 编辑:程序博客网 时间:2024/05/22 16:45


最近发现一个奇怪的bug,注册OnAudioPortUpdateListener后,却没有收到onAudioPatchListUpdate callback

debug后发现android在这一块有个bug


可以看下OnAudioPortUpdateListener的注册过程

AudioManager.java:    public void registerAudioPortUpdateListener(OnAudioPortUpdateListener l) {        sAudioPortEventHandler.init();        sAudioPortEventHandler.registerListener(l);    }


sAudioPortEventHandler是一个event handle,它接受来自native层的event,并调用OnAudioPortUpdateListener中的call,在它的Init函数中和native层联系起来


    void init() {        synchronized (this) {            if (mHandler != null) {                return;            }            // find the looper for our new event handler            Looper looper = Looper.getMainLooper();            if (looper != null) {                mHandler = new Handler(looper) {                };                native_setup(new WeakReference<AudioPortEventHandler>(this));            } else {                mHandler = null;            }        }    }

native_setup会通过jni调到native层:

static voidandroid_media_AudioSystem_eventHandlerSetup(JNIEnv *env, jobject thiz, jobject weak_this){    ALOGV("eventHandlerSetup");    sp<JNIAudioPortCallback> callback = new JNIAudioPortCallback(env, thiz, weak_this);    if (AudioSystem::addAudioPortCallback(callback) == NO_ERROR) {        setJniCallback(env, thiz, callback);    }}

这里象调用了AudioSystem的addAudioPortCallback, JNIAudioPortCallback在收到natvie层的callback后,向java层的AudioPortEventHandler发送消息


status_t AudioSystem::addAudioPortCallback(const sp<AudioPortCallback>& callback){    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();    if (aps == 0) return PERMISSION_DENIED;    Mutex::Autolock _l(gLockAPS);    if (gAudioPolicyServiceClient == 0) {        return NO_INIT;    }    int ret = gAudioPolicyServiceClient->addAudioPortCallback(callback);    if (ret == 1) {        aps->setAudioPortCallbacksEnabled(true);    }    return (ret < 0) ? INVALID_OPERATION : NO_ERROR;}

每个AudioSystem都是AudioPolicyService的一个client,在get_audio_policy_service()里会生成两个全局的binder,一个BpBinder,用于AudioSystem向AudioPolicyService发生消息,一个BnBinder,用于AudioPolicyService向AudioSystem发生消息,BnBinder就是AudioPolicyServiceClient. 然后把callback加到AudioPolicyServiceClient中去.

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();}


bug马上要出现了,接下来看看  get_audio_policy_service()

// establish binder interface to AudioPolicy serviceconst sp<IAudioPolicyService> AudioSystem::get_audio_policy_service(){    sp<IAudioPolicyService> ap;    sp<AudioPolicyServiceClient> apc;    {        Mutex::Autolock _l(gLockAPS);        if (gAudioPolicyService == 0) {            sp<IServiceManager> sm = defaultServiceManager();            sp<IBinder> binder;            do {                binder = sm->getService(String16("media.audio_policy"));                if (binder != 0)                    break;                ALOGW("AudioPolicyService not published, waiting...");                usleep(500000); // 0.5 s            } while (true);            if (gAudioPolicyServiceClient == NULL) {                gAudioPolicyServiceClient = new AudioPolicyServiceClient();            }            binder->linkToDeath(gAudioPolicyServiceClient);            gAudioPolicyService = interface_cast<IAudioPolicyService>(binder);            LOG_ALWAYS_FATAL_IF(gAudioPolicyService == 0);            apc = gAudioPolicyServiceClient;        }        ap = gAudioPolicyService;    }    if (apc != 0) {        ap->registerClient(apc);    }    return ap;}

按照前面的解释,很好理解,为当前进程生成全局的BpBInder( gAudioPolicyService) 和BnBinder(gAudioPolicyServiceClient), 然后调用gAudioPolicyService->registerClient


// A notification client is always registered by AudioSystem when the client process// connects to AudioPolicyService.void AudioPolicyService::registerClient(const sp<IAudioPolicyServiceClient>& client){    Mutex::Autolock _l(mNotificationClientsLock);    uid_t uid = IPCThreadState::self()->getCallingUid();    if (mNotificationClients.indexOfKey(uid) < 0) {        sp<NotificationClient> notificationClient = new NotificationClient(this,                                                                           client,                                                                           uid);        ALOGV("registerClient() client %p, uid %d", client.get(), uid);        mNotificationClients.add(uid, notificationClient);        sp<IBinder> binder = IInterface::asBinder(client);        binder->linkToDeath(notificationClient);    }}

问题就出在这里了,这里通过检查uid来查看client是否已经注册了,如果几个进程共享uid的话,这里的client就没有加mNotificationClients里去,也就不会收到callback,

可以看一下,这IAudioPolicyServiceClient目前只有三个callback,几乎也没有app使用,所以还没有什么问题.如果用进程号的话,应该能解决这个问题.

class IAudioPolicyServiceClient : public IInterface{public:    DECLARE_META_INTERFACE(AudioPolicyServiceClient);    // Notifies a change of audio port configuration.    virtual void onAudioPortListUpdate() = 0;    // Notifies a change of audio patch configuration.    virtual void onAudioPatchListUpdate() = 0;    // Notifies a change in the mixing state of a specific mix in a dynamic audio policy    virtual void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state) = 0;};

至于callack的过程,就是一个相反的过程,event的源头都是AudioPolicyManager中的openOutput, closeOutput, startOutput, openInput, closeInput, startInput



下一遍打算详细介绍下audioPatch...



0 0
原创粉丝点击