Binder机制看这里 Binde机智 这是一个分割符 Binder机智+ 分割(goutou) Binder机制++
MediaPlayerService多媒体框架中一个非常重要的服务。MediaPlayerService 我原称之为链接之王
图片来源
- MediaPlayer 是客户端 C/S 中的C
- MediaPlayerService MediaPlayerService::Client 是服务端 C/S中的S
- MediaPlayerService 实现 IMediaPlayerService 定义的业务逻辑,主要功能就是MediaPlayer::setDataSource 调用create创建对应的player
- MediaPlayerService::Client 实现IMediaPlayer 定义业务逻辑 start stop pause…; 是通过MediaPlayerService create的player中对应的方法 实现具体功能。
- 通过Transact 函数 向 IBinder 发出调用, 通过 onTransact 函数 使远程对象 相应接收到的调用
Binder通信时,需要通过IBinder接口转化具体的实体对象,就会产生可多可多类。
-
看上图Bp/Bn开头的类。他们都派生自两个类
· Bp??? : I??? : BpRefBase
· Bn??? : I??? : BBinder
· 都派生自 I??? 有嘛不同?- Bp 把对应的 binder_transaction_data 打包,通过BpRefBase的mRemote(BpBinder)发送出去,等待结果 - Bn 实现对应的业务逻辑,通过调用Bn派生类中的方法来实现,例如:MediaPlayerService::Client.继承了 BnMediaPlayer。
-
BpRefBase 中 remote函数用来与Binder驱动交互
-
Binder是用来从Binder驱动中接收相关请求并进行相关处理的
-
BpBinder 和 BinderDriver进行互通
- BBinder与BpBinder这两者容易混淆。其实这两者是很好区分 - 对于service来说继承了BBinder(BnInterface)因为BBinder有onTransact消息处理函数 - 对于与service通信的client来说需要继承BpBinder(BpInterface),因为BpBinder有消息传递函数transcat。 以cameraService的client为例 Camera.cpp中getCameraService函数取得远程CameraService的IBinder对象 然后通过 mCameraService = interface_cast<ICameraService>(binder); 进行重构得到了BpCameraService对象。而BpCameraService继承了BpInterface。 cameraService:defaultServiceManager()->addService(String16("media.camera"), new CameraService()); 传入了BBinder。IPC传递的过程中IBinder指针不可缺少,这个指针对一个进程来说就像是socket的ID一样,唯一的。所以不管这个IBinder是BBinder还是BpBinder, 他们的都是在重构BpBinder或者BBinder的时候把IBinder作为参数传入。 此段文字来自https://blog.csdn.net/RationalGo/article/details/23845085
看MediaPlayerService 先看 MediaPlayerService.cpp
class IMediaPlayerService : public IInterface
{public:DECLARE_META_INTERFACE(MediaPlayerService);virtual sp < IMediaPlayer > create (pid_t pid, const sp<IMediaPlayerClient>& client, const char* url) = 0;virtual sp < IMediaPlayer > create (pid_t pid, const sp<IMediaPlayerClient>& client, int fd, int64_t offset, int64_t length) = 0;virtual sp < IMemory > decode (const char * url, uint32_t *pSampleRate, int* pNumChannels) = 0;virtual sp < IMemory > decode (int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels) = 0;
};
class BnMediaPlayerService : public BnInterface<IMediaPlayerService>
{public:virtual status_tonTransact (uint32_t code,const Parcel & data,Parcel * reply,uint32_t flags = 0);
};
可以看到这里定义了一些常规播放控制接口。
找到入口
int main(int argc __unused, char** argv)
{signal(SIGPIPE, SIG_IGN);char value[PROPERTY_VALUE_MAX];//...sp<ProcessState> proc(ProcessState::self());sp<IServiceManager> sm = defaultServiceManager();//...AudioFlinger::instantiate();//AudioFlingerMediaPlayerService::instantiate();CameraService::instantiate();AudioPolicyService::instantiate();//AudioPolicyServiceSoundTriggerHwService::instantiate();registerExtensions();ProcessState::self()->startThreadPool();IPCThreadState::self()->joinThreadPool();//...
}
找 defaultServiceManager()
defaultServiceManager返回的实际是一个BpServiceManger类实例,并调用add函数;
B p MediaPlayService 作为服务代理端,那么 B n MediaPlayerService 一定是实现端; (注意一个Bp 一个 Bn)
MediaPlayerService 继承自 BnMediaPlayerService,实现了真正的业务函数。
此处省略一堆
最终BpServiceManager 的 addService 的 结果就是 MediaPlayerService的服务器端 已经再ServiceManager注册了。
BinderDriver和MediaPlayer通信的过程
客户端如何获得服务的代理并和服务器端通信?
MediaPlayer为例:
MediaPlayer::decode 方法中:getMediaPlayerService(),客户端向ServiceManager 查询服务并获得代理BpServiceManager,然后调用getService向ServiceManager 查询名叫 String16(”media.palyer“)的服务;
getService方法内,先将请求打包成Parcel,然后调用remote -> transact函数,最终调用的是IPCThreadStae的transact函数。
每个线程都有一个IPCThreadState ,IPCThreadState实例登记在Linux线程的上下文附属数据中,主要负责Binder的读写,请求处理框架。
IPCThreadState再构造的时候获取进程的ProcessState并记录再自己的成员变量中。
最终调用ProcessState::getStrongProxyForHandle函数。
这里的handle就是ServiceManager内维护的MediaPlayerService对应的Binder句柄,这个ProcessState根据这个句柄新建了一个BpBinder,并将其保存起来,下次需要ServiceManager请求获取相同句柄的时候就可以直接返回了。
根据返回的BpBinder 获得 MediaPlayerService的代理。
效用IMediaPlayerService的asInterface宏函数,这样就获得了一个代理BpMediaPlayerService对象,它的remote为BpBinder(handle),这个handle就是向ServiceManager查询到的MediaPlayerService对应的Binder句柄。
总结:
- MediaPlayer::setDataSource 会创建一个 MediaPlayerService::Client对应的BpMediaPlayer,用于获取MediaPlayerService::Client的各项功能。
- 只有MediaPlayerService向ServiceManager进行注册,MediaPlayer才能找到MediaPlayerService::Client; SO MediaPlayer必须先获取BpMediaPlayerService,然后通过BpMediaPlayerService 创建一个MediaPlayerService::Client。
可以去这里看书 Android 音视频开发
我看的书是 《Android 音视频开发》何俊林 著 公司被别人垫显示器的,不知道放了几年没人看的旧书,也是新书(木有人翻看过),😈