当前位置:网站首页>Audio audiorecord binder communication mechanism
Audio audiorecord binder communication mechanism
2022-07-06 03:02:00 【Cmatrix204】
Android Interprocess communication is widely used IPC signal communication , Combing AudioRecord In relevant processes ,IAudioFlinger、AudioFlinger,IAudioPolicyService、AudioPolicyService Between is through Binder Communicating , Combined with specific Audio Use examples of Binder Sort out the communication .
One 、 be based on AudioFlinger analysis Binder Establishment of communication mechanism
1.frameworks/native/libs/binder/include/binder/IInterface.h
Template interface class INTERFACE, This template interface class is Service Provided interface ,INTERFACE Need to inherit Binder Interface provided by communication library IInterface.
Local service interface 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();
};
Remote proxy interface 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 Agreement code agreed by both parties
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 Template interface class of communication IAudioFlinger
frameworks/av/media/libaudioclient/include/media/IAudioFlinger.h
Template interface class IAudioFlinger Inherit Binder Interface provided by communication library IInterface.
class IAudioFlinger : public IInterface
{
public:
DECLARE_META_INTERFACE(AudioFlinger); // The default interface declared by macro definition ,AudioFlinger yes Bn The service interface of the end instance
...
/* 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;
};
...
// These are pure virtual functions , It needs to be implemented under the interface that inherits it
/* 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 Local interface for communication BnAudioFlinger
frameworks/av/media/libaudioclient/include/media/IAudioFlinger.h
Bn( Local ) End Service BnAudioFlinger Inherit BnInterface Interface .
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
Local interface onTransact() Inherited from BBinder, After the process receives the service request , Different local interfaces will be called according to the received service request , And fill in the return value reply in , after binder The library will complete all events communicating with the driver .
code: Input , Indicates the agreement code agreed by both parties
data: Input , Save the parameters required by the interface .
reply: Output , The output value of the interface is saved in this class .
flags: Some special configuration information .
IMPLEMENT_META_INTERFACE(AudioFlinger, "android.media.IAudioFlinger"); // Template interface class
// ----------------------------------------------------------------------
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); // Judge whether the request is the corresponding proxy object IAudioFlinger Sent by , If not , Will not continue to carry out
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 It is still a pure virtual function , There is no implementation of local createRecord Such as the interface ,Bn( Local ) Service interface from end instance AudioFlinger, take AudioFlinger Sign up to service manager The implementation is in BinderService To implement inside .
#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
The concrete realization is AudioFlinger.cpp in
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 Terminal AudioFlinger Through integration BinderService The public interface of will Local class FregServer By service name AudioFlinger Sign up to service manager in .
template<typename SERVICE>
class BinderService
{
public:
// The static method used to register the service
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 Remote proxy interface for communication BpAudioFlinger
frameworks/av/media/libaudioclient/IAudioFlinger.cpp
writeInterfaceToken Write the communication header to the input data data in ,remote() Back to a BpBinder, So here we call BpBinder Of transact Method , Send the communication request to the server , Then return the result reply Read the return data of the server in .
The process of cross process communication is encapsulated , For users, the processing results of the local interface can be directly returned through the proxy interface .
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); // Template interface class IAudioFlinger The defined method is used to parse input data
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 End Client Specific trigger of
frameworks/av/media/libaudioclient/AudioRecord.cpp
AudioRecord create Stage makes a simple trigger AudioFlinger Binder Communication action .
// 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) Use it here AudioFlingerClinet A Binder signal communication Client The death monitoring function of the terminal , Reception of actual communication 、 Processing or using the local interface AudioFlinger The treatment that was carried out .
// 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 Integrated Binder Death notification monitoring implementation
//*/
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;
}
Two 、 ordinary AudioFlingerClient Binder Analysis of death monitoring mechanism
1.frameworks/av/media/libaudioclient/include/media/IAudioFlingerClient.h
Template interface class IAudioFlingerClient、 Local service interface BnAudioFlingerClient The definitions are all here .
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
Distal 、 The implementation of local service interface is here
// Distal Client Implementation of service interface
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);
}
};
// Implementation of local service interface
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
Local Bn The specific interface of virtual function is defined in AudioSystem.h, Realize in 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
// When passed Binder Far end detected client Conduct corresponding processing in relevant status
//*/
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:
...
}
summary :
Binder Interprocess communication mechanism is widely used in Android Camera、Audio Between modules , At the same time Binder The bottom implementation of communication : Process passing open Turn on the device , And pass mmap After setting the memory mapping area , Re pass ioctl() The way , Use binder Some protocols of driver definition are related to binder The mechanism of communication also has a lot of information and content worthy of in-depth study .
边栏推荐
- [Yunju entrepreneurial foundation notes] Chapter II entrepreneur test 18
- Yyds dry inventory comparison of several database storage engines
- 手写数据库客户端
- Microsoft speech synthesis assistant v1.3 text to speech tool, real speech AI generator
- OCR文字識別方法綜述
- A copy can also produce flowers
- 华为、H3C、思科命令对比,思维导图形式从基础、交换、路由三大方向介绍【转自微信公众号网络技术联盟站】
- Summary of Bible story reading
- Pat 1046 shortest distance (20 points) simulation
- The difference between sizeof and strlen in C language
猜你喜欢
OCR文字識別方法綜述
Pure QT version of Chinese chess: realize two-man, man-machine and network games
如何精准识别主数据?
主数据管理理论与实践
Which ecology is better, such as Mi family, graffiti, hilink, zhiting, etc? Analysis of five mainstream smart brands
主数据管理(MDM)的成熟度
PMP practice once a day | don't get lost in the exam -7.5
Gifcam v7.0 minimalist GIF animation recording tool Chinese single file version
Apt installation ZABBIX
Linear regression and logistic regression
随机推荐
[Yunju entrepreneurial foundation notes] Chapter II entrepreneur test 20
主数据管理(MDM)的成熟度
【Kubernetes 系列】一文学会Kubernetes Service安全的暴露应用
The difference between sizeof and strlen in C language
Fault analysis | analysis of an example of MySQL running out of host memory
【 kubernets series】 a Literature Study on the Safe exposure Applications of kubernets Service
Résumé des méthodes de reconnaissance des caractères ocr
【指针训练——八道题】
Classic interview question [gem pirate]
Force buckle 146 LRU cache
Redis SDS principle
ERA5再分析资料下载攻略
Maturity of master data management (MDM)
2345 file shredding, powerful file deletion tool, unbound pure extract version
Gifcam v7.0 minimalist GIF animation recording tool Chinese single file version
Briefly describe the implementation principle of redis cluster
Redis cluster deployment based on redis5
【Unity3D】GUI控件
Elimination games
[kubernetes series] learn the exposed application of kubernetes service security