IAudioManager.cpp源码如下:
源码路径:https://cs.android.com/android/platform/superproject/main/+/main:frameworks/native/services/audiomanager/IAudioManager.cpp;drc=84410fbd18148d422d3581201c67f1a72a6658c4;l=147?hl=zh-cn
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "IAudioManager"
//#define LOG_NDEBUG 0
#include <utils/Log.h>
#include <stdint.h>
#include <sys/types.h>
#include <binder/Parcel.h>
#include <audiomanager/AudioManager.h>
#include <audiomanager/IAudioManager.h>
namespace android {
class BpAudioManager : public BpInterface<IAudioManager>
{
public:
explicit BpAudioManager(const sp<IBinder>& impl)
: BpInterface<IAudioManager>(impl)
{
}
virtual audio_unique_id_t trackPlayer(player_type_t playerType, audio_usage_t usage,
audio_content_type_t content, const sp<IBinder>& player, audio_session_t sessionId) {
Parcel data, reply;
data.writeInterfaceToken(IAudioManager::getInterfaceDescriptor());
data.writeInt32(1); // non-null PlayerIdCard parcelable
// marshall PlayerIdCard data
data.writeInt32((int32_t) playerType);
// write attributes of PlayerIdCard
data.writeInt32((int32_t) usage);
data.writeInt32((int32_t) content);
data.writeInt32(0 /*source: none here, this is a player*/);
data.writeInt32(0 /*flags*/);
// write attributes' tags
data.writeInt32(1 /*FLATTEN_TAGS*/);
data.writeString16(String16("")); // no tags
// write attributes' bundle
data.writeInt32(-1977 /*ATTR_PARCEL_IS_NULL_BUNDLE*/); // no bundle
// write IPlayer
data.writeStrongBinder(player);
// write session Id
data.writeInt32((int32_t)sessionId);
// get new PIId in reply
const status_t res = remote()->transact(TRACK_PLAYER, data, &reply, 0);
if (res != OK || reply.readExceptionCode() != 0) {
ALOGE("trackPlayer() failed, piid is %d", PLAYER_PIID_INVALID);
return PLAYER_PIID_INVALID;
} else {
const audio_unique_id_t piid = (audio_unique_id_t) reply.readInt32();
ALOGV("trackPlayer() returned piid %d", piid);
return piid;
}
}
virtual status_t playerAttributes(audio_unique_id_t piid, audio_usage_t usage,
audio_content_type_t content) {
Parcel data, reply;
data.writeInterfaceToken(IAudioManager::getInterfaceDescriptor());
data.writeInt32((int32_t) piid);
data.writeInt32(1); // non-null AudioAttributes parcelable
data.writeInt32((int32_t) usage);
data.writeInt32((int32_t) content);
data.writeInt32(0 /*source: none here, this is a player*/);
data.writeInt32(0 /*flags*/);
// write attributes' tags
data.writeInt32(1 /*FLATTEN_TAGS*/);
data.writeString16(String16("")); // no tags
// write attributes' bundle
data.writeInt32(-1977 /*ATTR_PARCEL_IS_NULL_BUNDLE*/); // no bundle
return remote()->transact(PLAYER_ATTRIBUTES, data, &reply, IBinder::FLAG_ONEWAY);
}
virtual status_t playerEvent(audio_unique_id_t piid, player_state_t event,
audio_port_handle_t eventId) {
Parcel data, reply;
data.writeInterfaceToken(IAudioManager::getInterfaceDescriptor());
data.writeInt32((int32_t) piid);
data.writeInt32((int32_t) event);
data.writeInt32((int32_t) eventId);
return remote()->transact(PLAYER_EVENT, data, &reply, IBinder::FLAG_ONEWAY);
}
virtual status_t releasePlayer(audio_unique_id_t piid) {
Parcel data, reply;
data.writeInterfaceToken(IAudioManager::getInterfaceDescriptor());
data.writeInt32((int32_t) piid);
return remote()->transact(RELEASE_PLAYER, data, &reply, IBinder::FLAG_ONEWAY);
}
virtual audio_unique_id_t trackRecorder(const sp<IBinder>& recorder) {
Parcel data, reply;
data.writeInterfaceToken(IAudioManager::getInterfaceDescriptor());
data.writeStrongBinder(recorder);
// get new RIId in reply
const status_t res = remote()->transact(TRACK_RECORDER, data, &reply, 0);
if (res != OK || reply.readExceptionCode() != 0) {
ALOGE("trackRecorder() failed, riid is %d", RECORD_RIID_INVALID);
return RECORD_RIID_INVALID;
} else {
const audio_unique_id_t riid = (audio_unique_id_t) reply.readInt32();
ALOGV("trackRecorder() returned riid %d", riid);
return riid;
}
}
virtual status_t recorderEvent(audio_unique_id_t riid, recorder_state_t event) {
Parcel data, reply;
data.writeInterfaceToken(IAudioManager::getInterfaceDescriptor());
data.writeInt32((int32_t) riid);
data.writeInt32((int32_t) event);
return remote()->transact(RECORDER_EVENT, data, &reply, IBinder::FLAG_ONEWAY);
}
virtual status_t releaseRecorder(audio_unique_id_t riid) {
Parcel data, reply;
data.writeInterfaceToken(IAudioManager::getInterfaceDescriptor());
data.writeInt32((int32_t) riid);
return remote()->transact(RELEASE_RECORDER, data, &reply, IBinder::FLAG_ONEWAY);
}
virtual status_t playerSessionId(audio_unique_id_t piid, audio_session_t sessionId) {
Parcel data, reply;
data.writeInterfaceToken(IAudioManager::getInterfaceDescriptor());
data.writeInt32((int32_t) piid);
data.writeInt32((int32_t) sessionId);
return remote()->transact(PLAYER_SESSION_ID, data, &reply, IBinder::FLAG_ONEWAY);
}
virtual status_t portEvent(audio_port_handle_t portId, player_state_t event,
const std::unique_ptr<os::PersistableBundle>& extras) {
Parcel data, reply;
data.writeInterfaceToken(IAudioManager::getInterfaceDescriptor());
data.writeInt32((int32_t) portId);
data.writeInt32((int32_t) event);
// TODO: replace PersistableBundle with own struct
data.writeNullableParcelable(extras);
return remote()->transact(PORT_EVENT, data, &reply, IBinder::FLAG_ONEWAY);
}
};
IMPLEMENT_META_INTERFACE(AudioManager, "android.media.IAudioService");
// ----------------------------------------------------------------------------
}; // namespace android
这里显示了一个名为 IAudioManager.cpp 的文件,它是一个 C++ 语言的源代码文件,用于实现音频管理器的接口。代码的逻辑如下:
- 定义了一个 BpAudioManager 类,它继承了 BpInterface 类,用于实现 Binder 通信的代理端。
- 在 BpAudioManager 类中,实现了 IAudioManager 接口中的各个方法,包括:
- trackPlayer:用于追踪一个播放器的类型、用途、内容、会话 ID 等信息,并返回一个唯一的播放器 ID。
- playerAttributes:用于更新一个播放器的用途和内容属性。
- playerEvent:用于通知一个播放器的状态变化,如开始、暂停、停止等。
- releasePlayer:用于释放一个播放器的资源。
- trackRecorder:用于追踪一个录音器的引用,并返回一个唯一的录音器 ID。
- recorderEvent:用于通知一个录音器的状态变化,如开始、暂停、停止等。
- releaseRecorder:用于释放一个录音器的资源。
- playerSessionId:用于更新一个播放器的会话 ID。
- portEvent:用于通知一个端口的事件,如连接、断开、配置等。
- 使用 IMPLEMENT_META_INTERFACE 宏来注册 AudioManager 接口的名称和描述。
explicit BpAudioManager(const sp<IBinder>& impl)
: BpInterface<IAudioManager>(impl)
{
}
这是是一个 C++ 语言的构造函数,用于创建一个 BpAudioManager 对象。这个构造函数的参数是一个 IBinder 类型的智能指针,用于指向 Binder 通信的远程端。这个构造函数的作用是调用 BpInterface 类的构造函数,将 impl 作为参数传递,从而初始化 BpAudioManager 对象的基类成员变量。这个构造函数没有其他的操作,所以函数体为空。
virtual audio_unique_id_t trackPlayer(player_type_t playerType, audio_usage_t usage,
audio_content_type_t content, const sp<IBinder>& player, audio_session_t sessionId) {
Parcel data, reply;
data.writeInterfaceToken(IAudioManager::getInterfaceDescriptor());
data.writeInt32(1); // non-null PlayerIdCard parcelable
// marshall PlayerIdCard data
data.writeInt32((int32_t) playerType);
// write attributes of PlayerIdCard
data.writeInt32((int32_t) usage);
data.writeInt32((int32_t) content);
data.writeInt32(0 /*source: none here, this is a player*/);
data.writeInt32(0 /*flags*/);
// write attributes' tags
data.writeInt32(1 /*FLATTEN_TAGS*/);
data.writeString16(String16("")); // no tags
// write attributes' bundle
data.writeInt32(-1977 /*ATTR_PARCEL_IS_NULL_BUNDLE*/); // no bundle
// write IPlayer
data.writeStrongBinder(player);
// write session Id
data.writeInt32((int32_t)sessionId);
// get new PIId in reply
const status_t res = remote()->transact(TRACK_PLAYER, data, &reply, 0);
if (res != OK || reply.readExceptionCode() != 0) {
ALOGE("trackPlayer() failed, piid is %d", PLAYER_PIID_INVALID);
return PLAYER_PIID_INVALID;
} else {
const audio_unique_id_t piid = (audio_unique_id_t) reply.readInt32();
ALOGV("trackPlayer() returned piid %d", piid);
return piid;
}
}
这是一个 C++ 语言的虚函数,用于追踪一个播放器的信息,并返回一个唯一的播放器 ID。这个函数的参数是:
- playerType:一个枚举类型,表示播放器的类型,如媒体播放器、声音池、硬件编解码器等。
- usage:一个枚举类型,表示播放器的用途,如闹钟、游戏、通话等。
- content:一个枚举类型,表示播放器的内容,如音乐、电影、语音等。
- player:一个 IBinder 类型的智能指针,用于指向播放器的远程接口。
- sessionId:一个整数类型,表示播放器的会话 ID,用于关联不同的音频流。
这个函数的逻辑如下:
- 创建一个 Parcel 对象 data,用于存储要发送的数据。
- 创建一个 Parcel 对象 reply,用于接收返回的数据。
- 调用 data.writeInterfaceToken() 方法,写入 AudioManager 接口的标识符,用于验证 Binder 通信的有效性。
- 调用 data.writeInt32() 方法,写入一个整数 1,表示要发送的 PlayerIdCard 对象不为空。
- 调用 data.writeInt32() 方法,写入 playerType 参数,表示播放器的类型。
- 调用 data.writeInt32() 方法,依次写入 usage 和 content 参数,表示播放器的用途和内容。
- 调用 data.writeInt32() 方法,写入两个 0,表示播放器的源和标志为空。
- 调用 data.writeInt32() 方法,写入一个整数 1,表示要发送的属性标签为 FLATTEN_TAGS。
- 调用 data.writeString16() 方法,写入一个空字符串,表示没有属性标签。
- 调用 data.writeInt32() 方法,写入一个整数 -1977,表示要发送的属性包为空。
- 调用 data.writeStrongBinder() 方法,写入 player 参数,表示播放器的远程接口。
- 调用 data.writeInt32() 方法,写入 sessionId 参数,表示播放器的会话 ID。
- 调用 remote()->transact() 方法,将 data 对象发送给远程端,并将返回的数据存储在 reply 对象中。传递的参数是 TRACK_PLAYER,表示要执行的操作是追踪播放器,以及 0,表示不需要阻塞等待返回。
- 判断返回的状态是否为 OK,以及 reply 对象中是否有异常代码,如果有,则打印错误日志,并返回一个无效的播放器 ID。
- 如果没有异常,则从 reply 对象中读取一个整数,作为新分配的播放器 ID,并打印日志,然后返回该 ID。
简而言之,这个函数是用于追踪一个播放器的信息,并返回一个唯一的播放器 ID 的 AudioManager 接口的虚函数。
virtual status_t playerAttributes(audio_unique_id_t piid, audio_usage_t usage,
audio_content_type_t content) {
Parcel data, reply;
data.writeInterfaceToken(IAudioManager::getInterfaceDescriptor());
data.writeInt32((int32_t) piid);
data.writeInt32(1); // non-null AudioAttributes parcelable
data.writeInt32((int32_t) usage);
data.writeInt32((int32_t) content);
data.writeInt32(0 /*source: none here, this is a player*/);
data.writeInt32(0 /*flags*/);
// write attributes' tags
data.writeInt32(1 /*FLATTEN_TAGS*/);
data.writeString16(String16("")); // no tags
// write attributes' bundle
data.writeInt32(-1977 /*ATTR_PARCEL_IS_NULL_BUNDLE*/); // no bundle
return remote()->transact(PLAYER_ATTRIBUTES, data, &reply, IBinder::FLAG_ONEWAY);
}
这段代码是一个 C++ 语言的虚函数,用于更新一个播放器的用途和内容属性。这个函数的参数是:
- piid:一个整数类型,表示播放器的唯一 ID。
- usage:一个枚举类型,表示播放器的用途,如闹钟、游戏、通话等。
- content:一个枚举类型,表示播放器的内容,如音乐、电影、语音等。
这个函数的逻辑如下:
- 创建一个 Parcel 对象 data,用于存储要发送的数据。
- 创建一个 Parcel 对象 reply,用于接收返回的数据。
- 调用 data.writeInterfaceToken() 方法,写入 AudioManager 接口的标识符,用于验证 Binder 通信的有效性。
- 调用 data.writeInt32() 方法,写入 piid 参数,表示播放器的唯一 ID。
- 调用 data.writeInt32() 方法,写入一个整数 1,表示要发送的 AudioAttributes 对象不为空。
- 调用 data.writeInt32() 方法,依次写入 usage 和 content 参数,表示播放器的用途和内容属性。
- 调用 data.writeInt32() 方法,写入两个 0,表示播放器的源和标志为空。
- 调用 data.writeInt32() 方法,写入一个整数 1,表示要发送的属性标签为 FLATTEN_TAGS。
- 调用 data.writeString16() 方法,写入一个空字符串,表示没有属性标签。
- 调用 data.writeInt32() 方法,写入一个整数 -1977,表示要发送的属性包为空。
- 调用 remote()->transact() 方法,将 data 对象发送给远程端,并将返回的数据存储在 reply 对象中。传递的参数是 PLAYER_ATTRIBUTES,表示要执行的操作是更新播放器的属性,以及 IBinder::FLAG_ONEWAY,表示不需要等待返回的结果。
简而言之,这个函数是用于更新一个播放器的用途和内容属性的 AudioManager 接口的虚函数。
virtual status_t playerEvent(audio_unique_id_t piid, player_state_t event,
audio_port_handle_t eventId) {
Parcel data, reply;
data.writeInterfaceToken(IAudioManager::getInterfaceDescriptor());
data.writeInt32((int32_t) piid);
data.writeInt32((int32_t) event);
data.writeInt32((int32_t) eventId);
return remote()->transact(PLAYER_EVENT, data, &reply, IBinder::FLAG_ONEWAY);
}
这段代码是一个 C++ 语言的虚函数,用于通知一个播放器的状态变化。这个函数的参数是:
- piid:一个整数类型,表示播放器的唯一 ID。
- event:一个枚举类型,表示播放器的状态,如开始、暂停、停止等。
- eventId:一个整数类型,表示播放器的事件 ID,用于区分不同的事件。
这个函数的逻辑如下:
- 创建一个 Parcel 对象 data,用于存储要发送的数据。
- 创建一个 Parcel 对象 reply,用于接收返回的数据。
- 调用 data.writeInterfaceToken() 方法,写入 AudioManager 接口的标识符,用于验证 Binder 通信的有效性。
- 调用 data.writeInt32() 方法,依次写入 piid、event 和 eventId 参数,表示播放器的 ID、状态和事件 ID。
- 调用 remote()->transact() 方法,将 data 对象发送给远程端,并将返回的数据存储在 reply 对象中。传递的参数是 PLAYER_EVENT,表示要执行的操作是通知播放器的状态变化,以及 IBinder::FLAG_ONEWAY,表示不需要等待返回的结果。
简而言之,这个函数是用于通知一个播放器的状态变化的 AudioManager 接口的虚函数。
virtual status_t releasePlayer(audio_unique_id_t piid) {
Parcel data, reply;
data.writeInterfaceToken(IAudioManager::getInterfaceDescriptor());
data.writeInt32((int32_t) piid);
return remote()->transact(RELEASE_PLAYER, data, &reply, IBinder::FLAG_ONEWAY);
}
这是一个 C++ 语言的虚函数,用于释放一个播放器的资源。这个函数的参数是:
- piid:一个整数类型,表示播放器的唯一 ID。
这个函数的逻辑如下:
- 创建一个 Parcel 对象 data,用于存储要发送的数据。
- 创建一个 Parcel 对象 reply,用于接收返回的数据。
- 调用 data.writeInterfaceToken() 方法,写入 AudioManager 接口的标识符,用于验证 Binder 通信的有效性。
- 调用 data.writeInt32() 方法,写入 piid 参数,表示播放器的唯一 ID。
- 调用 remote()->transact() 方法,将 data 对象发送给远程端,并将返回的数据存储在 reply 对象中。传递的参数是 RELEASE_PLAYER,表示要执行的操作是释放播放器的资源,以及 IBinder::FLAG_ONEWAY,表示不需要等待返回的结果。
简而言之,这个函数是用于释放一个播放器的资源的 AudioManager 接口的虚函数。
virtual audio_unique_id_t trackRecorder(const sp<IBinder>& recorder) {
Parcel data, reply;
data.writeInterfaceToken(IAudioManager::getInterfaceDescriptor());
data.writeStrongBinder(recorder);
// get new RIId in reply
const status_t res = remote()->transact(TRACK_RECORDER, data, &reply, 0);
if (res != OK || reply.readExceptionCode() != 0) {
ALOGE("trackRecorder() failed, riid is %d", RECORD_RIID_INVALID);
return RECORD_RIID_INVALID;
} else {
const audio_unique_id_t riid = (audio_unique_id_t) reply.readInt32();
ALOGV("trackRecorder() returned riid %d", riid);
return riid;
}
}
这是一个 C++ 语言的虚函数,用于追踪一个录音器的引用,并返回一个唯一的录音器 ID。这个函数的参数是:
- recorder:一个 IBinder 类型的智能指针,用于指向录音器的远程接口。
这个函数的逻辑如下:
- 创建一个 Parcel 对象 data,用于存储要发送的数据。
- 创建一个 Parcel 对象 reply,用于接收返回的数据。
- 调用 data.writeInterfaceToken() 方法,写入 AudioManager 接口的标识符,用于验证 Binder 通信的有效性。
- 调用 data.writeStrongBinder() 方法,写入 recorder 参数,表示录音器的远程接口。
- 调用 remote()->transact() 方法,将 data 对象发送给远程端,并将返回的数据存储在 reply 对象中。传递的参数是 TRACK_RECORDER,表示要执行的操作是追踪录音器,以及 0,表示不需要阻塞等待返回。
- 判断返回的状态是否为 OK,以及 reply 对象中是否有异常代码,如果有,则打印错误日志,并返回一个无效的录音器 ID。
- 如果没有异常,则从 reply 对象中读取一个整数,作为新分配的录音器 ID,并打印日志,然后返回该 ID。
简而言之,这个函数是用于追踪一个录音器的引用,并返回一个唯一的录音器 ID 的 AudioManager 接口的虚函数。
virtual status_t recorderEvent(audio_unique_id_t riid, recorder_state_t event) {
Parcel data, reply;
data.writeInterfaceToken(IAudioManager::getInterfaceDescriptor());
data.writeInt32((int32_t) riid);
data.writeInt32((int32_t) event);
return remote()->transact(RECORDER_EVENT, data, &reply, IBinder::FLAG_ONEWAY);
}
这段代码是一个 C++ 语言的虚函数,用于通知一个录音器的状态变化。这个函数的参数是:
- riid:一个整数类型,表示录音器的唯一 ID。
- event:一个枚举类型,表示录音器的状态,如开始、暂停、停止等。
这个函数的逻辑如下:
- 创建一个 Parcel 对象 data,用于存储要发送的数据。
- 创建一个 Parcel 对象 reply,用于接收返回的数据。
- 调用 data.writeInterfaceToken() 方法,写入 AudioManager 接口的标识符,用于验证 Binder 通信的有效性。
- 调用 data.writeInt32() 方法,依次写入 riid 和 event 参数,表示录音器的 ID 和状态。
- 调用 remote()->transact() 方法,将 data 对象发送给远程端,并将返回的数据存储在 reply 对象中。传递的参数是 RECORDER_EVENT,表示要执行的操作是通知录音器的状态变化,以及 IBinder::FLAG_ONEWAY,表示不需要等待返回的结果。
简而言之,这个函数是用于通知一个录音器的状态变化的 AudioManager 接口的虚函数。
virtual status_t releaseRecorder(audio_unique_id_t riid) {
Parcel data, reply;
data.writeInterfaceToken(IAudioManager::getInterfaceDescriptor());
data.writeInt32((int32_t) riid);
return remote()->transact(RELEASE_RECORDER, data, &reply, IBinder::FLAG_ONEWAY);
}
这是一个 C++ 语言的虚函数,用于释放一个录音器的资源。这个函数的参数是:
- riid:一个整数类型,表示录音器的唯一 ID。
这个函数的逻辑如下: - 创建一个 Parcel 对象 data,用于存储要发送的数据。
- 创建一个 Parcel 对象 reply,用于接收返回的数据。
- 调用 data.writeInterfaceToken() 方法,写入 AudioManager 接口的标识符,用于验证 Binder 通信的有效性。
- 调用 data.writeInt32() 方法,写入 riid 参数,表示录音器的唯一 ID。
- 调用 remote()->transact() 方法,将 data 对象发送给远程端,并将返回的数据存储在 reply 对象中。传递的参数是 RELEASE_RECORDER,表示要执行的操作是释放录音器的资源,以及 IBinder::FLAG_ONEWAY,表示不需要等待返回的结果。
简而言之,这个函数是用于释放一个录音器的资源的 AudioManager 接口的虚函数
virtual status_t playerSessionId(audio_unique_id_t piid, audio_session_t sessionId) {
Parcel data, reply;
data.writeInterfaceToken(IAudioManager::getInterfaceDescriptor());
data.writeInt32((int32_t) piid);
data.writeInt32((int32_t) sessionId);
return remote()->transact(PLAYER_SESSION_ID, data, &reply, IBinder::FLAG_ONEWAY);
}
这段代码是一个 C++ 语言的虚函数,用于更新一个播放器的会话 ID。这个函数的参数是:
- piid:一个整数类型,表示播放器的唯一 ID。
- sessionId:一个整数类型,表示播放器的会话 ID,用于关联不同的音频流。
这个函数的逻辑如下:
- 创建一个 Parcel 对象 data,用于存储要发送的数据。
- 创建一个 Parcel 对象 reply,用于接收返回的数据。
- 调用 data.writeInterfaceToken() 方法,写入 AudioManager 接口的标识符,用于验证 Binder 通信的有效性。
- 调用 data.writeInt32() 方法,依次写入 piid 和 sessionId 参数,表示播放器的 ID 和会话 ID。
- 调用 remote()->transact() 方法,将 data 对象发送给远程端,并将返回的数据存储在 reply 对象中。传递的参数是 PLAYER_SESSION_ID,表示要执行的操作是更新播放器的会话 ID,以及 IBinder::FLAG_ONEWAY,表示不需要等待返回的结果。
简而言之,这个函数是用于更新一个播放器的会话 ID 的 AudioManager 接口的虚函数。
virtual status_t portEvent(audio_port_handle_t portId, player_state_t event,
const std::unique_ptr<os::PersistableBundle>& extras) {
Parcel data, reply;
data.writeInterfaceToken(IAudioManager::getInterfaceDescriptor());
data.writeInt32((int32_t) portId);
data.writeInt32((int32_t) event);
// TODO: replace PersistableBundle with own struct
data.writeNullableParcelable(extras);
return remote()->transact(PORT_EVENT, data, &reply, IBinder::FLAG_ONEWAY);
}
这段代码是一个 C++ 语言的虚函数,用于通知一个端口的事件。这个函数的参数是:
- portId:一个整数类型,表示端口的唯一 ID。
- event:一个枚举类型,表示端口的事件,如连接、断开、配置等。
- extras:一个智能指针,指向一个 os::PersistableBundle 类型的对象,用于存储额外的信息。
这个函数的逻辑如下:
- 创建一个 Parcel 对象 data,用于存储要发送的数据。
- 创建一个 Parcel 对象 reply,用于接收返回的数据。
- 调用 data.writeInterfaceToken() 方法,写入 AudioManager 接口的标识符,用于验证 Binder 通信的有效性。
- 调用 data.writeInt32() 方法,依次写入 portId 和 event 参数,表示端口的 ID 和事件。
- 调用 data.writeNullableParcelable() 方法,写入 extras 参数,表示额外的信息。如果 extras 为空,则写入一个空的 Parcelable 对象。
- 调用 remote()->transact() 方法,将 data 对象发送给远程端,并将返回的数据存储在 reply 对象中。传递的参数是 PORT_EVENT,表示要执行的操作是通知端口的事件,以及 IBinder::FLAG_ONEWAY,表示不需要等待返回的结果。
简而言之,这个函数是用于通知一个端口的事件的 AudioManager 接口的虚函数。
IMPLEMENT_META_INTERFACE(AudioManager, "android.media.IAudioService");
这是是一个 C++ 语言的宏定义,用于实现 AudioManager 接口的两个方法,分别是:
- getInterfaceDescriptor():用于返回 AudioManager 接口的标识符,即 “android.media.IAudioService”。
- asInterface():用于将一个 IBinder 类型的对象转换为一个 IAudioManager 类型的对象,如果该对象是本地对象并且实现了 AudioManager 接口,则返回其实际对象,否则返回一个代理对象。
这个宏定义的参数是:
- INTERFACE:表示接口的名称,即 AudioManager。
- NAME:表示接口的标识符,即 “android.media.IAudioService”。
简而言之,这个宏定义是用于实现 AudioManager 接口的两个方法的简化写法。
这里asInterface()在这里面可以看到
https://cs.android.com/android/platform/superproject/main/+/main:frameworks/native/libs/binder/include/binder/IInterface.h;drc=84410fbd18148d422d3581201c67f1a72a6658c4;l=115?hl=zh-cn