当前位置:网站首页>Audio-AudioRecord Binder通信机制

Audio-AudioRecord Binder通信机制

2022-07-06 02:59:00 Cmatrix204

        Android进程间通信大量使用IPC通信,在梳理AudioRecord相关流程中,IAudioFlinger、AudioFlinger,IAudioPolicyService、AudioPolicyService之间就是通过Binder进行通信的,结合具体的Audio的使用实例对Binder通信进行一些整理。

一、基于AudioFlinger解析Binder通信机制建立

1.frameworks/native/libs/binder/include/binder/IInterface.h     

        模板接口类INTERFACE,这个模板接口类就是Service提供的接口,INTERFACE需要继承Binder通信库提供的接口IInterface。

本地服务接口BnInterface

template<typename INTERFACE>
class BnInterface : public INTERFACE, public BBinder
{
public:
    virtual sp<IInterface>      queryLocalInterface(const String16& _descriptor);
    virtual const String16&     getInterfaceDescriptor() const;

protected:
    typedef INTERFACE           BaseInterface;
    virtual IBinder*            onAsBinder();
};

远程代理接口BpInterface

template<typename INTERFACE>
class BpInterface : public INTERFACE, public BpRefBase
{
public:
    explicit                    BpInterface(const sp<IBinder>& remote);

protected:
    typedef INTERFACE           BaseInterface;
    virtual IBinder*            onAsBinder();
};

2.AudioFlinger Binder通信双方约定的协议代码

frameworks/av/media/libaudioclient/IAudioFlinger.cpp

enum {
    CREATE_TRACK = IBinder::FIRST_CALL_TRANSACTION,
    CREATE_RECORD,
    SAMPLE_RATE,
    RESERVED,   // obsolete, was CHANNEL_COUNT
    FORMAT,

    ...

    SET_STREAM_MUTE,
    STREAM_VOLUME,
    STREAM_MUTE,
    SET_MODE,
    SET_MIC_MUTE,
    GET_MIC_MUTE,
    SET_RECORD_SILENCED,
    SET_PARAMETERS,
    GET_PARAMETERS,
    REGISTER_CLIENT,
    GET_INPUTBUFFERSIZE,
    OPEN_OUTPUT,
    OPEN_DUPLICATE_OUTPUT,
    CLOSE_OUTPUT,
    SUSPEND_OUTPUT,
    RESTORE_OUTPUT,
    OPEN_INPUT,
    CLOSE_INPUT,
    INVALIDATE_STREAM,
    SET_VOICE_VOLUME,
    GET_RENDER_POSITION,
    GET_INPUT_FRAMES_LOST,
    
    ...    

};

#define MAX_ITEMS_PER_LIST 1024

3.AudioFlinger Binder通信的模版接口类IAudioFlinger

frameworks/av/media/libaudioclient/include/media/IAudioFlinger.h

        模版接口类IAudioFlinger继承Binder通信库提供的接口IInterface.

class IAudioFlinger : public IInterface
{
public:
    DECLARE_META_INTERFACE(AudioFlinger); //通过宏定义声明的默认接口,AudioFlinger是Bn端实例的服务接口

    ...

    /* CreateTrackInput contains all input arguments sent by AudioTrack to AudioFlinger
     * when calling createTrack() including arguments that will be updated by AudioFlinger
     * and returned in CreateTrackOutput object
     */
    class CreateTrackInput : public Parcelable {
    public:
        status_t readFromParcel(const Parcel *parcel) override {
            /* input arguments*/
            memset(&attr, 0, sizeof(audio_attributes_t));
            if (parcel->read(&attr, sizeof(audio_attributes_t)) != NO_ERROR) {
                return DEAD_OBJECT;
            }
            attr.tags[AUDIO_ATTRIBUTES_TAGS_MAX_SIZE -1] = '\0';
            memset(&config, 0, sizeof(audio_config_t));
            if (parcel->read(&config, sizeof(audio_config_t)) != NO_ERROR) {
                return DEAD_OBJECT;
            }
            if (clientInfo.readFromParcel(parcel) != NO_ERROR) {
                return DEAD_OBJECT;
            }
            if (parcel->readInt32() != 0) {
                // TODO: Using unsecurePointer() has some associated security
                //       pitfalls (see declaration for details).
                //       Either document why it is safe in this case or address
                //       the issue (e.g. by copying).
                sharedBuffer = interface_cast<IMemory>(parcel->readStrongBinder());
                if (sharedBuffer == 0 || sharedBuffer->unsecurePointer() == NULL) {
                    return BAD_VALUE;
                }
            }
            notificationsPerBuffer = parcel->readInt32();
            speed = parcel->readFloat();
            audioTrackCallback = interface_cast<media::IAudioTrackCallback>(
                    parcel->readStrongBinder());

            /* input/output arguments*/
            (void)parcel->read(&flags, sizeof(audio_output_flags_t));
            frameCount = parcel->readInt64();
            notificationFrameCount = parcel->readInt64();
            (void)parcel->read(&selectedDeviceId, sizeof(audio_port_handle_t));
            (void)parcel->read(&sessionId, sizeof(audio_session_t));
            return NO_ERROR;
        }

        status_t writeToParcel(Parcel *parcel) const override {
            /* input arguments*/
            (void)parcel->write(&attr, sizeof(audio_attributes_t));
            (void)parcel->write(&config, sizeof(audio_config_t));
            (void)clientInfo.writeToParcel(parcel);
            if (sharedBuffer != 0) {
                (void)parcel->writeInt32(1);
                (void)parcel->writeStrongBinder(IInterface::asBinder(sharedBuffer));
            } else {
                (void)parcel->writeInt32(0);
            }
            (void)parcel->writeInt32(notificationsPerBuffer);
            (void)parcel->writeFloat(speed);
            (void)parcel->writeStrongBinder(IInterface::asBinder(audioTrackCallback));

            /* input/output arguments*/
            (void)parcel->write(&flags, sizeof(audio_output_flags_t));
            (void)parcel->writeInt64(frameCount);
            (void)parcel->writeInt64(notificationFrameCount);
            (void)parcel->write(&selectedDeviceId, sizeof(audio_port_handle_t));
            (void)parcel->write(&sessionId, sizeof(audio_session_t));
            return NO_ERROR;
        }

        /* input */
        audio_attributes_t attr;
        audio_config_t config;
        AudioClient clientInfo;
        sp<IMemory> sharedBuffer;
        uint32_t notificationsPerBuffer;
        float speed;
        sp<media::IAudioTrackCallback> audioTrackCallback;

        /* input/output */
        audio_output_flags_t flags;
        size_t frameCount;
        size_t notificationFrameCount;
        audio_port_handle_t selectedDeviceId;
        audio_session_t sessionId;
    };

    ...
        
    //这些都是纯虚函数,需要在继承它的接口下进行实现
    /* create an audio track and registers it with AudioFlinger.
     * return null if the track cannot be created.
     */
    virtual sp<IAudioTrack> createTrack(const CreateTrackInput& input,
                                        CreateTrackOutput& output,
                                        status_t *status) = 0;

    virtual sp<media::IAudioRecord> createRecord(const CreateRecordInput& input,
                                        CreateRecordOutput& output,
                                        status_t *status) = 0;

    // FIXME Surprisingly, format/latency don't work for input handles

    /* query the audio hardware state. This state never changes,
     * and therefore can be cached.
     */
    virtual     uint32_t    sampleRate(audio_io_handle_t ioHandle) const = 0;

    // reserved; formerly channelCount()

    virtual     audio_format_t format(audio_io_handle_t output) const = 0;
    virtual     size_t      frameCount(audio_io_handle_t ioHandle) const = 0;

    // return estimated latency in milliseconds
    virtual     uint32_t    latency(audio_io_handle_t output) const = 0;

    ...

}

 4.AudioFlinger Binder通信的本地接口BnAudioFlinger

frameworks/av/media/libaudioclient/include/media/IAudioFlinger.h

        Bn(本地)端Service BnAudioFlinger继承BnInterface接口.

class BnAudioFlinger : public BnInterface<IAudioFlinger>
{
public:
    virtual status_t    onTransact( uint32_t code,
                                    const Parcel& data,
                                    Parcel* reply,
                                    uint32_t flags = 0);

    // Requests media.log to start merging log buffers
    virtual void requestLogMerge() = 0;
};

frameworks/av/media/libaudioclient/IAudioFlinger.cpp

        本地端接口的onTransact()继承自BBinder,进程收到服务请求后,会根据收到的服务请求调用本地不同的接口,并将返回值填入reply中,之后binder库会完成与驱动通信的所有事件。

code:输入,表示双方约定的协议代码

data:输入,保存了接口需要的参数等。

reply:输出,接口的输出值保存在这个类中。

flags:一些特殊的配置信息。

IMPLEMENT_META_INTERFACE(AudioFlinger, "android.media.IAudioFlinger"); //模版接口类

// ----------------------------------------------------------------------

status_t BnAudioFlinger::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    // make sure transactions reserved to AudioPolicyManager do not come from other processes
    switch (code) {
        case SET_STREAM_VOLUME:
        case SET_STREAM_MUTE:
        case OPEN_OUTPUT:
        case OPEN_DUPLICATE_OUTPUT:
        case CLOSE_OUTPUT:
        case SUSPEND_OUTPUT:
        case RESTORE_OUTPUT:
        case OPEN_INPUT:
        case CLOSE_INPUT:

        ...

        switch (code) {
        case CREATE_TRACK: {
            CHECK_INTERFACE(IAudioFlinger, data, reply); //判断请求是不是对应的代理对象IAudioFlinger发送过来的,如果不是,就不会继续往下执行

            CreateTrackInput input;
            if (input.readFromParcel((Parcel*)&data) != NO_ERROR) {
                reply->writeInt32(DEAD_OBJECT);
                return NO_ERROR;
            }

            status_t status;
            CreateTrackOutput output;

            sp<IAudioTrack> track= createTrack(input,
                                               output,
                                               &status);

            LOG_ALWAYS_FATAL_IF((track != 0) != (status == NO_ERROR));
            reply->writeInt32(status);
            if (status != NO_ERROR) {
                return NO_ERROR;
            }
            reply->writeStrongBinder(IInterface::asBinder(track));
            output.writeToParcel(reply);
            return NO_ERROR;
        } break;
        case CREATE_RECORD: {
            CHECK_INTERFACE(IAudioFlinger, data, reply);

            CreateRecordInput input;
            if (input.readFromParcel((Parcel*)&data) != NO_ERROR) {
                reply->writeInt32(DEAD_OBJECT);
                return NO_ERROR;
            }

            status_t status;
            CreateRecordOutput output;

            sp<media::IAudioRecord> record = createRecord(input,
                                                          output,
                                                          &status);

            LOG_ALWAYS_FATAL_IF((record != 0) != (status == NO_ERROR));
            reply->writeInt32(status);
            if (status != NO_ERROR) {
                return NO_ERROR;
            }
            reply->writeStrongBinder(IInterface::asBinder(record));
            output.writeToParcel(reply);
            return NO_ERROR;
        } break;
        case SAMPLE_RATE: {
            CHECK_INTERFACE(IAudioFlinger, data, reply);
            reply->writeInt32( sampleRate((audio_io_handle_t) data.readInt32()) );
            return NO_ERROR;
        } break;
}

 frameworks/av/services/audioflinger/AudioFlinger.h

        BnAudioFlinger依然是纯虚函数,并没有实现本地端的createRecord等接口,Bn(本地)端实例出的服务接口AudioFlinger,将AudioFlinger注册到service manager里面的实现是在BinderService里面实现。

#define INCLUDING_FROM_AUDIOFLINGER_H

class AudioFlinger :
    public BinderService<AudioFlinger>,
    public BnAudioFlinger
{
    friend class BinderService<AudioFlinger>;   // for AudioFlinger()

public:
    static const char* getServiceName() ANDROID_API { return "media.audio_flinger"; }

    virtual     status_t    dump(int fd, const Vector<String16>& args);

    // IAudioFlinger interface, in binder opcode order
    virtual sp<IAudioTrack> createTrack(const CreateTrackInput& input,
                                        CreateTrackOutput& output,
                                        status_t *status);

    virtual sp<media::IAudioRecord> createRecord(const CreateRecordInput& input,
                                                 CreateRecordOutput& output,
                                                 status_t *status);


    ...

}

 frameworks/av/services/audioflinger/AudioFlinger.cpp

        具体实现在AudioFlinger.cpp中

AudioFlinger::AudioFlinger()
    : BnAudioFlinger(),
      mMediaLogNotifier(new AudioFlinger::MediaLogNotifier()),
      mPrimaryHardwareDev(NULL),
      mAudioHwDevs(NULL),
      mHardwareStatus(AUDIO_HW_IDLE),
      mMasterVolume(1.0f),
      mMasterMute(false),
      // mNextUniqueId(AUDIO_UNIQUE_ID_USE_MAX),
      mMode(AUDIO_MODE_INVALID),
      mBtNrecIsOff(false),
      mIsLowRamDevice(true),
      mIsDeviceTypeKnown(false),
      mTotalMemory(0),
      mClientSharedHeapSize(kMinimumClientSharedHeapSizeBytes),
      mGlobalEffectEnableTime(0),
      mPatchPanel(this),
      mDeviceEffectManager(this),
      mSystemReady(false)
{

    // unsigned instead of audio_unique_id_use_t, because ++ operator is unavailable for enum
    for (unsigned use = AUDIO_UNIQUE_ID_USE_UNSPECIFIED; use < AUDIO_UNIQUE_ID_USE_MAX; use++) {
        // zero ID has a special meaning, so unavailable
        mNextUniqueIds[use] = AUDIO_UNIQUE_ID_USE_MAX;
    }


    /* get property and set mSYSTEM_READY */
    const bool systemreadyStatus = property_get_bool("af.media.systemready.state", false);
    if (systemreadyStatus) {
       mSystemReady = true;
    }

    const bool doLog = property_get_bool("ro.test_harness", false);
    if (doLog) {
        mLogMemoryDealer = new MemoryDealer(kLogMemorySize, "LogWriters",
                MemoryHeapBase::READ_ONLY);
        (void) pthread_once(&sMediaLogOnce, sMediaLogInit);
    }

    // reset battery stats.
    // if the audio service has crashed, battery stats could be left
    // in bad state, reset the state upon service start.
    BatteryNotifier::getInstance().noteResetAudio();

    mDevicesFactoryHal = DevicesFactoryHalInterface::create();
    mEffectsFactoryHal = EffectsFactoryHalInterface::create();

    mMediaLogNotifier->run("MediaLogNotifier");
    std::vector<pid_t> halPids;
    mDevicesFactoryHal->getHalPids(&halPids);
    TimeCheck::setAudioHalPids(halPids);
    // Notify that we have started (also called when audioserver service restarts)
    mediametrics::LogItem(mMetricsId)
        .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_CTOR)
        .record();
       
}


sp<media::IAudioRecord> AudioFlinger::createRecord(const CreateRecordInput& input,
                                                   CreateRecordOutput& output,
                                                   status_t *status)
{
    sp<RecordThread::RecordTrack> recordTrack;
    sp<RecordHandle> recordHandle;
    sp<Client> client;
    status_t lStatus;
    audio_session_t sessionId = input.sessionId;
    audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE;

    output.cblk.clear();
    output.buffers.clear();
    output.inputId = AUDIO_IO_HANDLE_NONE;


r (;;) {
    // release previously opened input if retrying.
    if (output.inputId != AUDIO_IO_HANDLE_NONE) {
        recordTrack.clear();
        AudioSystem::releaseInput(portId);
        output.inputId = AUDIO_IO_HANDLE_NONE;
        output.selectedDeviceId = input.selectedDeviceId;
        portId = AUDIO_PORT_HANDLE_NONE;
    }

    ...
    
    ALOGI("wsj-audioFlinger->createRecord getInputForAttr, sessionId: %d, clientPid: %d, clientUid: %d, input.opPackageName: %s, output.flags: %d", sessionId, clientPid, clientUid, String8(input.opPackageName).string(), output.flags);
    lStatus = AudioSystem::getInputForAttr(&input.attr, &output.inputId,
                                      input.riid,
                                      sessionId,
                                    // FIXME compare to AudioTrack
                                      clientPid,
                                      clientUid,
                                      input.opPackageName,
                                      &input.config,
                                      output.flags, &output.selectedDeviceId, &portId);
    if (lStatus != NO_ERROR) {
        ALOGE("createRecord() getInputForAttr return error %d", lStatus);
        goto Exit;
    }

    ...

        ALOGI("wsj-createRecord() AudioFlinger::createRecord lSessionId: %d input %d", sessionId, output.inputId);

        output.sampleRate = input.config.sample_rate;
        output.frameCount = input.frameCount;
        output.notificationFrameCount = input.notificationFrameCount;

        ALOGI("wsj-createRecord() AudioFlinger::createRecord createRecordTrack_l");
        recordTrack = thread->createRecordTrack_l(client, input.attr, &output.sampleRate,
                                                  input.config.format, input.config.channel_mask,
                                                  &output.frameCount, sessionId,
                                                  &output.notificationFrameCount,
                                                  callingPid, clientUid, &output.flags,
                                                  input.clientInfo.clientTid,
                                                  &lStatus, portId,
                                                  input.opPackageName);
        LOG_ALWAYS_FATAL_IF((lStatus == NO_ERROR) && (recordTrack == 0));

        // lStatus == BAD_TYPE means FAST flag was rejected: request a new input from
        // audio policy manager without FAST constraint
        if (lStatus == BAD_TYPE) {
            continue;
        }

        if (lStatus != NO_ERROR) {
            goto Exit;
        }

        // Check if one effect chain was awaiting for an AudioRecord to be created on this
        // session and move it to this thread.
        ALOGI("wsj-createRecord() AudioFlinger::createRecord getOrphanEffectChain_l");
        sp<EffectChain> chain = getOrphanEffectChain_l(sessionId);
        if (chain != 0) {
            Mutex::Autolock _l(thread->mLock);
            thread->addEffectChain_l(chain);
        }
        break;
    }
    // End of retry loop.
    // The lack of indentation is deliberate, to reduce code churn and ease merges.
    }

    output.cblk = recordTrack->getCblk();
    output.buffers = recordTrack->getBuffers();
    output.portId = portId;

    // return handle to client
    recordHandle = new RecordHandle(recordTrack);

    ...
}

...

frameworks/native/include/binder/BinderService.h

        Bn端的AudioFlinger通过集成BinderService的公共接口将 本地类FregServer通过服务名AudioFlinger注册到service manager中。

template<typename SERVICE>
class BinderService
{
public:
    //用来注册服务的静态方法
    static status_t publish(bool allowIsolated = false,
                            int dumpFlags = IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT) {
        sp<IServiceManager> sm(defaultServiceManager());
        return sm->addService(String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated,
                              dumpFlags);
    }

    static void publishAndJoinThreadPool(
            bool allowIsolated = false,
            int dumpFlags = IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT) {
        publish(allowIsolated, dumpFlags);
        joinThreadPool();
    }

    static void instantiate() { publish(); }

    static status_t shutdown() { return NO_ERROR; }

private:
    static void joinThreadPool() {
        sp<ProcessState> ps(ProcessState::self());
        ps->startThreadPool();
        ps->giveThreadPoolName();
        IPCThreadState::self()->joinThreadPool();
    }
};

5. AudioFlinger Binder通信的远程代理接口BpAudioFlinger

frameworks/av/media/libaudioclient/IAudioFlinger.cpp       

        writeInterfaceToken将通信头写入到输入数据data中,remote()返回的是一个BpBinder,所以这里调用了BpBinder的transact方法,将通信请求发送到服务端,再从返回结果reply中读出服务端的返回数据。

        这个跨进程通信的过程通过封装,对于用户来说是通过代理接口就可以直接返回本地接口的处理结果。

class BpAudioFlinger : public BpInterface<IAudioFlinger>
{
public:
    explicit BpAudioFlinger(const sp<IBinder>& impl)
        : BpInterface<IAudioFlinger>(impl)
    {
    }

    virtual sp<IAudioTrack> createTrack(const CreateTrackInput& input,
                                        CreateTrackOutput& output,
                                        status_t *status)
    {
        Parcel data, reply;
        sp<IAudioTrack> track;
        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());

        if (status == nullptr) {
            return track;
        }

        input.writeToParcel(&data); //模版接口类IAudioFlinger定义的方法用来解析input数据

        status_t lStatus = remote()->transact(CREATE_TRACK, data, &reply);
        if (lStatus != NO_ERROR) {
            ALOGE("createTrack transaction error %d", lStatus);
            *status = DEAD_OBJECT;
            return track;
        }
        *status = reply.readInt32();
        if (*status != NO_ERROR) {
            ALOGE("createTrack returned error %d", *status);
            return track;
        }
        track = interface_cast<IAudioTrack>(reply.readStrongBinder());
        if (track == 0) {
            ALOGE("createTrack returned an NULL IAudioTrack with status OK");
            *status = DEAD_OBJECT;
            return track;
        }
        output.readFromParcel(&reply);
        return track;
    }

    virtual sp<media::IAudioRecord> createRecord(const CreateRecordInput& input,
                                                 CreateRecordOutput& output,
                                                 status_t *status)
    {
        Parcel data, reply;
        sp<media::IAudioRecord> record;
        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());

        if (status == nullptr) {
            return record;
        }

        ALOGI("wsj-IaudioFlinger->createRecord input.writeToParcel(&data)");
        input.writeToParcel(&data);

        status_t lStatus = remote()->transact(CREATE_RECORD, data, &reply);
        if (lStatus != NO_ERROR) {
            ALOGE("createRecord transaction error %d", lStatus);
            *status = DEAD_OBJECT;
            return record;
        }
        *status = reply.readInt32();
        if (*status != NO_ERROR) {
            ALOGE("createRecord returned error %d", *status);
            return record;
        }

        record = interface_cast<media::IAudioRecord>(reply.readStrongBinder());
        if (record == 0) {
            ALOGE("createRecord returned a NULL IAudioRecord with status OK");
            *status = DEAD_OBJECT;
            return record;
        }
        
        ALOGI("wsj-IaudioFlinger->createRecord output.readFromParcel(&reply)");
        output.readFromParcel(&reply);
        return record;
    }

    ...

}

6.AudioFlinger bp端Client的具体触发

frameworks/av/media/libaudioclient/AudioRecord.cpp

        AudioRecord create阶段做了简单的触发AudioFlinger Binder通信动作。

// must be called with mLock held
status_t AudioRecord::createRecord_l(const Modulo<uint32_t> &epoch, const String16& opPackageName)
{
    const int64_t beginNs = systemTime();

    const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();

    IAudioFlinger::CreateRecordInput input;
    IAudioFlinger::CreateRecordOutput output;
    audio_session_t originalSessionId;
    sp<media::IAudioRecord> record;

    ...
}

frameworks/av/media/libaudioclient/AudioSystem.cpp

        binder->linkToDeath(gAudioFlingerClient)这边利用AudioFlingerClinet进行了一个Binder通信Client端的死亡监听的功能,实际上的通信的接收、处理还是利用的本地端接口AudioFlinger进行的处理。

// establish binder interface to AudioFlinger service
const sp<IAudioFlinger> AudioSystem::get_audio_flinger()
{
    sp<IAudioFlinger> af;
    sp<AudioFlingerClient> afc;
    bool reportNoError = false;
    {
        Mutex::Autolock _l(gLock);
        if (gAudioFlinger == 0) {
            sp<IServiceManager> sm = defaultServiceManager();
            sp<IBinder> binder;
            do {
                binder = sm->getService(String16("media.audio_flinger"));
                if (binder != 0)
                    break;
                ALOGW("AudioFlinger not published, waiting...");
                usleep(500000); // 0.5 s
            } while (true);
            if (gAudioFlingerClient == NULL) {
                gAudioFlingerClient = new AudioFlingerClient();
            } else {
                reportNoError = true;
            }

            ///*add by shengjie for parse AudioFlingerClient
            //AudioFlingerClient: public IBinder::DeathRecipient 集成了Binder死亡通知监听实现
            //*/
            binder->linkToDeath(gAudioFlingerClient);
            gAudioFlinger = interface_cast<IAudioFlinger>(binder);
            LOG_ALWAYS_FATAL_IF(gAudioFlinger == 0);
            afc = gAudioFlingerClient;
            // Make sure callbacks can be received by gAudioFlingerClient
            ProcessState::self()->startThreadPool();
        }
        af = gAudioFlinger;
    }
    if (afc != 0) {
        int64_t token = IPCThreadState::self()->clearCallingIdentity();
        af->registerClient(afc);
        IPCThreadState::self()->restoreCallingIdentity(token);
    }
    if (reportNoError) reportError(NO_ERROR);
    return af;
}

二、简单的AudioFlingerClient Binder死亡监听机制解析

1.frameworks/av/media/libaudioclient/include/media/IAudioFlingerClient.h

        模版接口类IAudioFlingerClient、本地服务接口BnAudioFlingerClient定义都在这边。

namespace android {

// ----------------------------------------------------------------------------

class IAudioFlingerClient : public IInterface
{
public:
    DECLARE_META_INTERFACE(AudioFlingerClient);

    // Notifies a change of audio input/output configuration.
    virtual void ioConfigChanged(audio_io_config_event event,
                                 const sp<AudioIoDescriptor>& ioDesc) = 0;

};


// ----------------------------------------------------------------------------

class BnAudioFlingerClient : public BnInterface<IAudioFlingerClient>
{
public:
    virtual status_t    onTransact( uint32_t code,
                                    const Parcel& data,
                                    Parcel* reply,
                                    uint32_t flags = 0);
};

// ----------------------------------------------------------------------------

}; // namespace android

2. frameworks/av/media/libaudioclient/IAudioFlingerClient.cpp

        远端、本地端服务接口的实现都在这边

//远端Client服务接口的实现
class BpAudioFlingerClient : public BpInterface<IAudioFlingerClient>
{
public:
    explicit BpAudioFlingerClient(const sp<IBinder>& impl)
        : BpInterface<IAudioFlingerClient>(impl)
    {
    }

    void ioConfigChanged(audio_io_config_event event, const sp<AudioIoDescriptor>& ioDesc)
    {
        Parcel data, reply;
        data.writeInterfaceToken(IAudioFlingerClient::getInterfaceDescriptor());
        data.writeInt32(event);
        data.writeInt32((int32_t)ioDesc->mIoHandle);
        data.write(&ioDesc->mPatch, sizeof(struct audio_patch));
        data.writeInt32(ioDesc->mSamplingRate);
        data.writeInt32(ioDesc->mFormat);
        data.writeInt32(ioDesc->mChannelMask);
        data.writeInt64(ioDesc->mFrameCount);
        data.writeInt64(ioDesc->mFrameCountHAL);
        data.writeInt32(ioDesc->mLatency);
        data.writeInt32(ioDesc->mPortId);
        remote()->transact(IO_CONFIG_CHANGED, data, &reply, IBinder::FLAG_ONEWAY);
    }
};



//本地服务接口的实现
IMPLEMENT_META_INTERFACE(AudioFlingerClient, "android.media.IAudioFlingerClient");
status_t BnAudioFlingerClient::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    switch (code) {
    case IO_CONFIG_CHANGED: {
            CHECK_INTERFACE(IAudioFlingerClient, data, reply);
            audio_io_config_event event = (audio_io_config_event)data.readInt32();
            sp<AudioIoDescriptor> ioDesc = new AudioIoDescriptor();
            ioDesc->mIoHandle = (audio_io_handle_t) data.readInt32();
            data.read(&ioDesc->mPatch, sizeof(struct audio_patch));
            ioDesc->mSamplingRate = data.readInt32();
            ioDesc->mFormat = (audio_format_t) data.readInt32();
            ioDesc->mChannelMask = (audio_channel_mask_t) data.readInt32();
            ioDesc->mFrameCount = data.readInt64();
            ioDesc->mFrameCountHAL = data.readInt64();
            ioDesc->mLatency = data.readInt32();
            ioDesc->mPortId = data.readInt32();
            ioConfigChanged(event, ioDesc);
            return NO_ERROR;
        } break;
        default:
            return BBinder::onTransact(code, data, reply, flags);
    }
}

...

3.frameworks/av/media/libaudioclient/include/media/AudioSystem.h

        本地Bn虚函数的具体接口定义在AudioSystem.h,实现在AudioSystem.cpp

class AudioFlingerClient: public IBinder::DeathRecipient, public BnAudioFlingerClient
    {
    public:
        AudioFlingerClient() :
            mInBuffSize(0), mInSamplingRate(0),
            mInFormat(AUDIO_FORMAT_DEFAULT), mInChannelMask(AUDIO_CHANNEL_NONE) {
        }

        void clearIoCache();
        status_t getInputBufferSize(uint32_t sampleRate, audio_format_t format,
                                    audio_channel_mask_t channelMask, size_t* buffSize);
        sp<AudioIoDescriptor> getIoDescriptor(audio_io_handle_t ioHandle);

        // DeathRecipient
        virtual void binderDied(const wp<IBinder>& who);

        // IAudioFlingerClient

        // indicate a change in the configuration of an output or input: keeps the cached
        // values for output/input parameters up-to-date in client process
        virtual void ioConfigChanged(audio_io_config_event event,
                                     const sp<AudioIoDescriptor>& ioDesc);



        ///*add by shengjie for parse AudioFlingerClient
        //当通过Binder检测到远端啊client相关状态时进行相应的处理
        //*/
        status_t addAudioDeviceCallback(const wp<AudioDeviceCallback>& callback,
                                               audio_io_handle_t audioIo,
                                               audio_port_handle_t portId);
        status_t removeAudioDeviceCallback(const wp<AudioDeviceCallback>& callback,
                                           audio_io_handle_t audioIo,
                                           audio_port_handle_t portId);

        audio_port_handle_t getDeviceIdForIo(audio_io_handle_t audioIo);

    private:
        Mutex                               mLock;

        DefaultKeyedVector<audio_io_handle_t, sp<AudioIoDescriptor> >   mIoDescriptors;

        std::map<audio_io_handle_t, std::map<audio_port_handle_t, wp<AudioDeviceCallback>>>
                mAudioDeviceCallbacks;
        // cached values for recording getInputBufferSize() queries
        size_t                              mInBuffSize;    // zero indicates cache is invalid
        uint32_t                            mInSamplingRate;
        audio_format_t                      mInFormat;
        audio_channel_mask_t                mInChannelMask;
        sp<AudioIoDescriptor> getIoDescriptor_l(audio_io_handle_t ioHandle);
    };

frameworks/av/media/libaudioclient/AudioSystem.cpp

status_t AudioSystem::AudioFlingerClient::removeAudioDeviceCallback(
        const wp<AudioDeviceCallback>& callback __unused, audio_io_handle_t audioIo,
        audio_port_handle_t portId)
{
    ALOGV("%s audioIo %d portId %d", __func__, audioIo, portId);
    Mutex::Autolock _l(mLock);
    auto it = mAudioDeviceCallbacks.find(audioIo);
    if (it == mAudioDeviceCallbacks.end()) {
        return INVALID_OPERATION;
    }
    if (it->second.erase(portId) == 0) {
        return INVALID_OPERATION;
    }
    if (it->second.size() == 0) {
        mAudioDeviceCallbacks.erase(audioIo);
    }
    return NO_ERROR;
}


void AudioSystem::AudioFlingerClient::ioConfigChanged(audio_io_config_event event,
                                                      const sp<AudioIoDescriptor>& ioDesc) {
    ALOGV("ioConfigChanged() event %d", event);

    if (ioDesc == 0 || ioDesc->mIoHandle == AUDIO_IO_HANDLE_NONE) return;

    audio_port_handle_t deviceId = AUDIO_PORT_HANDLE_NONE;
    std::vector<sp<AudioDeviceCallback>> callbacksToCall;
    {
        Mutex::Autolock _l(mLock);
        auto callbacks = std::map<audio_port_handle_t, wp<AudioDeviceCallback>>();

        switch (event) {
        case AUDIO_OUTPUT_OPENED:
        case AUDIO_OUTPUT_REGISTERED:
        case AUDIO_INPUT_OPENED:
        case AUDIO_INPUT_REGISTERED: {
            sp<AudioIoDescriptor> oldDesc = getIoDescriptor_l(ioDesc->mIoHandle);
            if (oldDesc == 0) {
                mIoDescriptors.add(ioDesc->mIoHandle, ioDesc);
            } else {
                deviceId = oldDesc->getDeviceId();
                mIoDescriptors.replaceValueFor(ioDesc->mIoHandle, ioDesc);
            }

            if (ioDesc->getDeviceId() != AUDIO_PORT_HANDLE_NONE) {
                deviceId = ioDesc->getDeviceId();
                if (event == AUDIO_OUTPUT_OPENED || event == AUDIO_INPUT_OPENED) {
                    auto it = mAudioDeviceCallbacks.find(ioDesc->mIoHandle);
                    if (it != mAudioDeviceCallbacks.end()) {
                        callbacks = it->second;
                    }
                }
            }
            ALOGV("ioConfigChanged() new %s %s %d samplingRate %u, format %#x channel mask %#x "
                    "frameCount %zu deviceId %d",
                    event == AUDIO_OUTPUT_OPENED || event == AUDIO_OUTPUT_REGISTERED ?
                            "output" : "input",
                            event == AUDIO_OUTPUT_OPENED || event == AUDIO_INPUT_OPENED ?
                            "opened" : "registered",
                    ioDesc->mIoHandle, ioDesc->mSamplingRate, ioDesc->mFormat, ioDesc->mChannelMask,
                    ioDesc->mFrameCount, ioDesc->getDeviceId());
            } break;
        case AUDIO_OUTPUT_CLOSED:


        ...

}

总结:

        Binder进程间通信机制广泛应用在Android Camera、Audio等各个模块之间,同时对于Binder通信的底层实现:进程通过open打开设备,并通过mmap设置好了内存映射区域后,再通过ioctl()的方式,使用binder驱动定义的一些协议与binder进行通信的机制也有着很多值得深入研究的信息与内容。

原网站

版权声明
本文为[Cmatrix204]所创,转载请带上原文链接,感谢
https://blog.csdn.net/Cmatrix204/article/details/125604050