IAudioManager.cpp源码解读

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
在这里插入图片描述

  • 27
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值