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;