当前位置:网站首页>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进行通信的机制也有着很多值得深入研究的信息与内容。
边栏推荐
- Custom attribute access__ getattribute__/ Settings__ setattr__/ Delete__ delattr__ method
- Linear regression and logistic regression
- [Yunju entrepreneurial foundation notes] Chapter II entrepreneur test 23
- 【 kubernets series】 a Literature Study on the Safe exposure Applications of kubernets Service
- Network Security Learning - Web vulnerabilities (Part 1)
- 2.12 simulation
- MySQL learning notes-10-tablespace recycling
- Era5 reanalysis data download strategy
- [Yunju entrepreneurial foundation notes] Chapter II entrepreneur test 14
- RobotFramework入门(二)appUI自动化之app启动
猜你喜欢
4. File modification
IPv6 jobs
[Chongqing Guangdong education] higher mathematics I reference materials of Southwest Petroleum University
【若依(ruoyi)】设置主题样式
【 kubernets series】 a Literature Study on the Safe exposure Applications of kubernets Service
微服务间通信
[ruoyi] enable Mini navigation bar
ReferenceError: primordials is not defined错误解决
OCR文字识别方法综述
不赚钱的科大讯飞,投资价值该怎么看?
随机推荐
【Kubernetes 系列】一文学会Kubernetes Service安全的暴露应用
[Digital IC manual tearing code] Verilog asynchronous reset synchronous release | topic | principle | design | simulation
tcpdump: no suitable device found
全国大学生信息安全赛创新实践赛初赛---misc(永恒的夜)
What is the investment value of iFLYTEK, which does not make money?
[matlab] access of variables and files
Prototype design
建模规范:命名规范
js 正则过滤和增加富文本中图片前缀
【若依(ruoyi)】ztree 自定义图标(iconSkin 属性)
Qt发布exe软件及修改exe应用程序图标
Reverse repackaging of wechat applet
GifCam v7.0 极简GIF动画录制工具中文单文件版
[Yunju entrepreneurial foundation notes] Chapter II entrepreneur test 6
[Yunju entrepreneurial foundation notes] Chapter II entrepreneur test 17
Apt installation ZABBIX
JS regular filtering and adding image prefixes in rich text
Deeply analyze the chain 2+1 mode, and subvert the traditional thinking of selling goods?
CSP date calculation
Huawei, H3C, Cisco command comparison, mind map form from the basic, switching, routing three directions [transferred from wechat official account network technology alliance station]