native服务器端MediadrmServer服务
主要参考《深入理解 Android 卷I》邓必山,虽然基于的android版本有点旧,但是一本经得起细读的好书
实际上这里是一个完整的客户端(service)访问服务器端(servicemanager),再是服务器端(service)响应客户端(client)
原理大致如下图所示:实际上client和server属于是两个进程,binder_driver就类似于网络。他将两者沟通在了一起。
Mediadrmserver实际上android的DRM服务,以前以为是android启动的时候就一定会加载的,但是里面填加的log在启动时候并没有输出(不排除log丢失)实际上极有可能是错误的
参考前一篇博文,这些服务是在android启动之后才加载的。所有直接在system/bin下面去手动执行就OK,system/bin下面的都属于是可执行文件 ./文件名就可以启动该服务。
frameworks/av/services/mediadrm$ vi main_mediadrmserver.cpp
int main() { signal(SIGPIPE, SIG_IGN); sp<ProcessState> proc(ProcessState::self()); sp<IServiceManager> sm = defaultServiceManager(); MediaDrmService::instantiate(); ProcessState::self()->startThreadPool();//启动服务,执行完该函数之后,到下一步的时候直接没有输出相应的信息,在关机的时候或者是强制退出的时候也没有出来 IPCThreadState::self()->joinThreadPool(); }
- ProcessState是每个进程只有一个对象,所以直接是单例模式。在Android中ProcessState是客户端和服务端公共的部分,作为Binder通信的基础,ProcessState是一个singleton类,每个
进程只有一个对象,这个对象负责打开Binder驱动,建立线程池,让其进程里面的所有线程都能通过Binder通信。 - IPCThreadState,每个线程都有一个IPCThreadState实例登记在Linux线程的上下文附属数据中,主要负责Binder的读取,写入和请求处理框架。IPCThreadState在构造的时候获取进程的ProcessState并记录在自己的成员变量。mProcess中,通过mProcess可以获得Binder的句柄。
- IServiceManager类属于是抽象的接口,所有的Service都需要被servicemanager,IServiceManager的派生类中实现将service添加到servicemanager里面去,目测这个派生类是
1、创建ProcessState实例
// 针对ProcessState定义的全局变量
Mutex gProcessMutex;
sp<ProcessState> gProcess;
sp<ProcessState> ProcessState::self() { Mutex::Autolock _l(gProcessMutex); //gProcess是在Static.cpp中定义的一个全局变量 //程序刚开始执行,gProcess一定为空,在程序启动之后,因为进程一直运行,所以进程的ProcessState对象是一直都存在,所以最好不要在这里输出信息,不然卡死。 if (gProcess != NULL) { return gProcess; } //创建一个ProcessState对象,并赋值给gProcess gProcess = new ProcessState;//为什么类后面不加上()呢?实际上C++new对象的时候是可以不加()的 return gProcess; }
sp<ProcessState> proc(ProcessState::self());实际的执行结果为
sp<ProcessState> proc(gProcess) 等价于
ProcessState *gProcess = new ProcessState ;
ProcessState * proc = gProcess;
实际上这里引入了两个指针对象 proc和gProcess,他们都是指向的同一块内存。
ProcessState::self()返回了一个全局的指针gProcess,深入他的构造函数。
ProcessState::ProcessState()
//Android中有很多代码都是这么写的,稍不留神就容易忽略这里调用了一个很重要的函数
: mDriverFD(open_driver()) //int mDriverFD;初始化为文件设备指针
, mVMStart(MAP_FAILED)//映射内存的起始地址void* mVMStart;
, mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)
, mThreadCountDecrement(PTHREAD_COND_INITIALIZER)
, mExecutingThreadsCount(0)
, mMaxThreads(DEFAULT_MAX_BINDER_THREADS)
, mStarvationStartTimeMs(0)
, mManagesContexts(false)
, mBinderContextCheckFunc(NULL)
, mBinderContextUserData(NULL)
, mThreadPoolStarted(false)//初始化为false,在启动线程池的时候有用到该变量
, mThreadPoolSeq(1)
{
if (mDriverFD >= 0) {//打开文件成功
// mmap the binder, providing a chunk of virtual address space to receive transactions.
// mmap binder 提供一块虚拟地址空间来接收事务
/*
BIDNER_VM_SIZE定义为(1*1024*1024)-(4096*2)=1M-8K
mmap的用法希望读者man一下,不过这个函数真正的实现和驱动有关系,而Binder驱动会分配一块内存来接收数据。实际上接收数据的binder驱动(所以感觉mVMStart没啥子用呢!),
也就是说这块空间实际上是在内核驱动中进行分配的,只是将他的虚拟地址映射过来了而已
*/
mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);// mDriverFD实际上是打开的设备的文件描述符,那这块空间是如何使用的呢?
if (mVMStart == MAP_FAILED) {
// *sigh*
ALOGE("Using /dev/binder failed: unable to mmap transaction memory.\n");
close(mDriverFD);
mDriverFD = -1;
}
}
LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver could not be opened. Terminating.");
}
主要是两个事1、open /dev/binder 2、分配虚拟地址空间,其中mmap函数之前在file_operations这个结构体中有所接触,功能为将设备内存映射到进程相应的虚拟地址空间去。
实际上内核空间已经划分了很多分的缓冲区出来。因为不止一个进程!!!
open_driver,/dev/binder这个设备。
static int open_driver()
{
// 它是Android在内核中为完成进程间通信而专门设置的一个虚拟设备
int fd = open("/dev/binder", O_RDWR | O_CLOEXEC);// 打开文件失败返回-1
if (fd >= 0) {
int vers = 0;
status_t result = ioctl(fd, BINDER_VERSION, &vers);
if (result == -1) {
ALOGE("Binder ioctl to obtain version failed: %s", strerror(errno));
close(fd);
fd = -1;
}
if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) {//ioctl中返回0是指的什么呢?应该是查询失败了,成功了才不为0
ALOGE("Binder driver protocol does not match user space protocol!");
close(fd);
fd = -1;
}
size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;
//通过ioctl方式告诉binder驱动,这个fd支持的最大线程数,一般是15个
result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
if (result == -1) {
ALOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
// 这里不close(fd);和fd=-1;???
}
} else {
ALOGW("Opening '/dev/binder' failed: %s\n", strerror(errno));
}
return fd;
}
2、创建IServiceManager对象
IserviceManager对象是通过defaultServiceManager函数生成的,defaultServiceManager这个函数是定义在命名空间android内的函数,所以可以直接使用,具体的实现在IServiceManager.cpp中。
和上面的gProcess一样,属于在static.cpp文件中定义的全局变量
// ------------ IServiceManager.cpp
Mutex gDefaultServiceManagerLock;
sp<IServiceManager> gDefaultServiceManager;
sp<IPermissionController> gPermissionController;
sp<IServiceManager> defaultServiceManager() { if (gDefaultServiceManager != NULL) return gDefaultServiceManager; { AutoMutex _l(gDefaultServiceManagerLock); //全局的锁 while (gDefaultServiceManager == NULL) { //真正的gDefaultServiceManager是在这里创建的 gDefaultServiceManager = interface_cast<IServiceManager>(ProcessState::self()->getContextObject(NULL)); if (gDefaultServiceManager == NULL) sleep(1); } } return gDefaultServiceManager; }
sp<IServiceManager> sm = defaultServiceManager();
等价于:sp<IServiceManager> sm = gDefaultServiceManager;
IServiceManager *sm = gDefaultServiceManager 这属于是最直接的等价了。
interface_cast<IServiceManager>(ProcessState::self()->getContextObject(NULL));如何产生IServiceManager类型的指针的呢?
该函数模板定义在IIterface.h文件中:
template<typename INTERFACE> inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj) { return INTERFACE::asInterface(obj); }
实际上转换为:
inline sp<IServiceManager> interface_cast(const sp<IBinder>&obj)
{
return IServiceManager::asinterface(obj);
}
传入的参数为:ProcessState::self()->getContextObject(NULL),实际上是IBinder类型的对象。实际上这里可以看出来sp<IBinder>和sp IBinder *这两个是不同的,因为sp<IBinder>后面是可以接上一用类型的。(没有充分理解引用在参数传递中的使用,实际上传入的是一个sp<IBinder>类型,传递进去的形式为以引用类型的形式传递进去的)
ProcessState::self()->getContextObject(NULL)如何产生sp<IBinder>类型的对象的呢?
PorcessState::self()返回的是gProcess指针,等价于gProcess->getContextObject(NULL);
interface_cast<IServiceManager>(gProcess->getContextObject(NULL));
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/) { return getStrongProxyForHandle(0); }
在ProcessState.cpp文件里面明显看到getContextObject是一个被重载了的operation,我们幸运的重载了第一个方法,这里注意是里面传入的是0,也就是handle为0,好像很重要!!!
等价于interface_cast<IServiceManager>( getStrongProxyForHandle(0));何必如此大费周章呢?我就是想得到一个对象而已。
struct handle_entry {//里面有如下两个成员 IBinder* binder; RefBase::weakref_type* refs; }; handle_entry* lookupHandleLocked(int32_t handle);//感觉这是之前一个被我忽视的重点函数
// 定义有下面这个Vector,里面的成员是handle_entry
Vector<handle_entry>mHandleToObject;
lookupHandleLocked函数:
ProcessState::handle_entry* ProcessState::lookupHandleLocked(int32_t handle) { const size_t N=mHandleToObject.size(); if (N <= (size_t)handle) {//如果handle是0,N应该是大于等于0吧 handle_entry e; e.binder = NULL; e.refs = NULL; status_t err = mHandleToObject.insertAt(e, N, handle+1-N);//插入的这三个数据分别表示的什么??? if (err < NO_ERROR) // 插入失败的时候返回的是NULL return NULL; } return &mHandleToObject.editItemAt(handle);// 就取的是刚刚插入的那个对象 }
已经迫不及待想进入IPCThreadState这个类了!!!
但是深入getStrongProxyForHandle函数发现,你竟然已经开始ping了。啥时候给你建立的连接啊!你竟然就开始ping了,一定是分析漏了什么。答案就在gProcess内!也就是我们最开始的时候提到的new ProcessState对象这里
原来在创建对象的时候就已经获取了设备描述符以及虚拟内存空间,接下来就是如何使用的问题了。
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle) { sp<IBinder> result; AutoMutex _l(mLock); /* 根据索引查找对应的资源。如果lookupHandleLocked发现没有对应的资源项,则会 创建一个新的项并返回。这个新项的内容需要填充。 */ handle_entry* e = lookupHandleLocked(handle); if (e != NULL) {// e一定不为空,因为在lookupHandleLocked中若为空这个是指N==0的情况,也会insert一个进去,为NULL只能是插入失败的情况了。 IBinder* b = e->binder;// 不好意思,刚好是NULL if (b == NULL || !e->refs->attemptIncWeak(this)) {//对于新创建的资源项,它的binder为空,所以走这个分支。注意,handle的值为0。 if (handle == 0) {// 刚好是0 Parcel data;// binder驱动通信相关的数据结构 status_t status = IPCThreadState::self()->transact(0, IBinder::PING_TRANSACTION, data, NULL, 0);//ping一下service_manager,确保他现在是联通,实际上在这里是不是就已经开始和service_manager进行通信了呢? if (status == DEAD_OBJECT) return NULL; } //创建一个BpBinder,BpBinder实际上是IBinder的子类 b = new BpBinder(handle); //子类转父类是可以直接转的,父类转子类需要强制 //填充entry的内容 e->binder = b;// 实际上赋值给了他的子类对象 if (b) e->refs = b->getWeakRefs(); result = b;// 赋值给全局的父类的对象IBinder,方便返回 } else { // This little bit of nastyness is to allow us to add a primary // reference to the remote proxy when this team doesn't have one // but another team is sending the handle to us. result.force_set(b); e->refs->decWeak(this); } } return result;//返回IBinder(handle)实际上是BpBinder(handle),注意,handle的值为0 }
IPCThreadState::self()->transact这个函数先放在这里(对于service来说,这里是ping一下service_manager是否连通?那对于client呢?)。回到主题,创建IServiceManager对象。
interface_cast<IServiceManager>(gProcess->getContextObject(NULL));
等价于interface_cast<IServiceManager>(new BpBinder(handle));
等价于:
inline sp<IServiceManager> interface_cast(const sp<IBinder>&obj)
{
return IServiceManager::asinterface(obj);
}
return IServiceManager::asinterface(new BpBinder(handle));
回到IServiceManager的asinterface函数。因为这里IServiceManager::asinterface为静态函数,所以可以直接通过类名来引用。来看看IServiceManager类的定义,里面涉及到两个相当重要的宏。
class IServiceManager : public IInterface { public: //关键无比的宏! DECLARE_META_INTERFACE(ServiceManager); //下面是IServiceManager所提供的业务函数 virtual sp<IBinder> getService( const String16& name) const = 0; virtual sp<IBinder> checkService( const String16& name) const = 0; virtual status_t addService( const String16& name, const sp<IBinder>& service, bool allowIsolated = false) = 0; virtual Vector<String16> listServices() = 0; enum { GET_SERVICE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION, CHECK_SERVICE_TRANSACTION, ADD_SERVICE_TRANSACTION, LIST_SERVICES_TRANSACTION, }; };
宏DECLEAR_META_INTERFACE定义了一些模板服务(数据类型前面都加上了命名空间)的实现,在service中十分常用。
// 下面两个宏是至关重要的两个宏 #define DECLARE_META_INTERFACE(INTERFACE) \ static const android::String16 descriptor; /*定义一个描述字符串*/ \ static android::sp<I##INTERFACE> asInterface( \ const android::sp<android::IBinder>& obj); /*定义一个asInterface函数*/ \ virtual const android::String16& getInterfaceDescriptor() const; /*定义一个getInterfaceDescriptor函数,估计就是返回descriptor字符串*/ \ I##INTERFACE(); /*定义IServiceManager的构造函数和析构函数 ##表示将该宏转换成字符串*/ \ virtual ~I##INTERFACE(); /*前面的I呢?我晕原来是IserviceManager前面的那个I*/ \
static android::sp<IServiceManager> asInterface(const android::sp<android::IBinder> &obj)
到他的实现的宏IMPLEMENT_META_INTERFACE里面。
申明是在IServiceManager.cpp文件中IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");
/* DECLARE宏声明了一些函数和一个变量,那么,IMPLEMENT 宏的作用肯定就是定义它们了。IMPLEMENT的定义在IInterface.h 中*/ #define IMPLEMENT_META_INTERFACE(INTERFACE, NAME) \ const android::String16 I##INTERFACE::descriptor(NAME); /* 成员初始化的一种方式*/ \ const android::String16& /*实现getInterfaceDescriptor函数*/ \ I##INTERFACE::getInterfaceDescriptor() const { \ return I##INTERFACE::descriptor; /*返回字符串descriptor,值是"android.os.IServiceManager" */ \ } \ android::sp<I##INTERFACE> I##INTERFACE::asInterface( \ const android::sp<android::IBinder>& obj) \ { \ android::sp<I##INTERFACE> intr; \ if (obj != NULL) { \ intr = static_cast<I##INTERFACE*>( \ obj->queryLocalInterface( \ I##INTERFACE::descriptor).get()); \ if (intr == NULL) { /*obj是我们刚才创建的那个BpBinder(0)*/ \ intr = new Bp##INTERFACE(obj); \ } \ } \ return intr; \ } \ I##INTERFACE::I##INTERFACE() { } \ I##INTERFACE::~I##INTERFACE() { } \
翻译一下:
static sp<IServiceManager> IServiceManager::asInterface(const sp<IBinder> &obj){ sp<IServiceManager> intr; if(obj !=NULL){ intr = static_cast<IServiceManager>(obj->queryLocalInterface(IServiceManager::descriptor).get()); if(intr==NULL){ intr = new BpServiceManager(obj); } } return intr; }
里面涉及到IBinder::queryLocalInterface(),在Binder技术篇(一)中提到,他实际上返回的是执行IIterface类型的对象,但是在IBinder中返回的是NULL,BpBinder、BBinder均没有实现。
继续在BBinder的子类BnInterface重载返回了this(本身)BpBinder的子类BpInterface没有实现,所以等价于。
intr = static_cast<IServiceManager>(NULL.get());还是NULL,所以直接new一个BpServiceManager对象。
intr = new BpServiceManager(obj); IServiceManager是BpServiceManager爸爸的爸爸(个人认为,android卷1中直接讲解的是他的爸爸),即我最后获取的服务实际上BpServiceManager的对象
return IServiceManager::asinterface(new BpBinder(handle));
return (new BpServiceManager(obj));
继续深入BpServiceManager(obj)的构造函数:这个在注册服务的时候将使用到。
BpServiceManager之所以感觉有点怪怪的,是因为他的父类定义的一个模板继承
template<typename INTERFACE>
class BpInterface : public INTERFACE, public BpRefBase // 有趣,传入的参数成了继承的类,实现了动态的继承,很多都是这样实现的
{
public:
BpInterface(const sp<IBinder>& remote);
protected:
virtual IBinder* onAsBinder();
};
INTERFACE决定了他的祖类。
class BpServiceManager : public BpInterface<IServiceManager>//决定了模板继承类的实现
{
public:
BpServiceManager(const sp<IBinder>& impl)//构造函数
: BpInterface<IServiceManager>(impl)// 调用父类的构造函数,他的分类有两个,到底是调用哪个呢?实际上说他的父类有两个这种说法是错误的
{
}
。。。。。。
};
BpInterface<IServiceManager>作为一个类来看待呢!实际上是调用了BpInterface<IServiceManager>这个类的构造函数
族谱关系应该是这样的,在另一篇博文中有错误,因为BpInterface类的不确定性,我们可以将BpInterface视为BpInterface<IServiceManager>,就有了将其视为一个整体的想法(个人意测)
template<typename INTERFACE>
inline BpInterface<INTERFACE>::BpInterface(const sp<IBinder>& remote)
: BpRefBase(remote)
{
}
调用BpInterface<IServiceManager>的构造函数BpInterface,然后里面又调用了祖类构造函数BpRefBase(remote)
[-->Binder.cpp::BpRefBase类]
// IBinder* const mRemote;
// RefBase::weakref_type* mRefs;
// std::atomic<int32_t> mState;
BpRefBase::BpRefBase(const sp<IBinder>& o)
: mRemote(o.get()), mRefs(NULL), mState(0)// .体现出他引用的特质,get在IBinder和BpBinder都关于这个的定义或者重载,所以初步推测是在他的父类上,只是被IBinder继承了。
{
extendObjectLifetime(OBJECT_LIFETIME_WEAK);
if (mRemote) {
mRemote->incStrong(this); // Removed on first IncStrong().
mRefs = mRemote->createWeak(this); // Held for our entire lifetime.
}
}
mRemote实际上是我们new BpBinder(handle)对象,他实际上是远程服务在本地的代理,有了他就可以远程服务进行通信了。
3、初始化instantiate
3.1业务层工作
void MediaDrmService::instantiate() { defaultServiceManager()->addService(String16("media.drm"), new MediaDrmService()); }
defaultServiceManager()返回的是刚刚我们生成的那个BpSeriveManager,为什么要提到BpServiceManager而不是提到IServiceManager呢?因为addService实际上是IService类的一个纯虚函数,他需要在子类中得以实现。
注意函数定义的是三个参数,但是默认只是传了两个进去,根据之前window编程的经验,他实际上是默认为0。
virtual status_t addService(const String16& name, const sp<IBinder>& service,bool allowIsolated) { Parcel data, reply; data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());//应该也属于是static函数 data.writeString16(name);//“media.drm” data.writeStrongBinder(service);// new MediaDrmService() MediaDrmService的对象 data.writeInt32(allowIsolated ? 1 : 0);//默认是0 status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);//remote()返回的是IBinder的对象吗?我感觉好像是BpBinder对象 return err == NO_ERROR ? reply.readExceptionCode() : err; }
来瞅瞅remote()返回的是啥?预知详情还需回头看BpServiceManager的构造函数。
remote( )返回的就是mRemote对象。
3.2通信层工作
IBinder::transact------>BpBinder::transact不然你还真可能找到BBinder里面去了。
我有点理解了为什么说BpBinder实际是道具了。
status_t BpBinder::transact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { // Once a binder has died, it will never come back to life. if (mAlive) {//初始化为1 //BpBinder果然是道具,它把transact工作交给了IPCThreadState status_t status = IPCThreadState::self()->transact(mHandle, code, data, reply, flags);//mHandle也是参数,最后一个参数默认是0 if (status == DEAD_OBJECT) mAlive = 0; return status; } return DEAD_OBJECT; }
好吧!又回到了IPCThreadState这个类。先暂时放这里,后面一起分析。
- 调用BpServiceManager的addService是一个业务层的函数
- · addService函数中把请求数据打包成data后,传给了BpBinder的transact函数,这是把通信的工作交给了BpBinder
3.2.1伙计IPCProcessState::self
- IPCThreadState,每个线程都有一个IPCThreadState实例登记在Linux线程的上下文附属数据中,主要负责Binder的读取,写入和请求处理框架。IPCThreadState在构造的时候获取进程的ProcessState并记录在自己的成员变量。mProcess中,通过mProcess可以获得Binder的句柄。
还记得在开始的时候,记录的比较清楚的,每个线程都有一个IPCProcessState,还应该关注的是mProcess后面会时常用到。
class IPCThreadState { public: static IPCThreadState* self();//单例模式,静态函数可以直接通过类名::函数名 进行引用 Parcel mIn;//发送命令缓冲区 Parcel mOut;//接收命令缓冲器
const sp<ProcessState> mProcess; // 进程的ProcessState对象
const pid_t mMyThreadId;//每个线程均有一个线程id
pid_t mCallingPid; // 进程ID
uid_t mCallingUid; // 用户id
};
这里主要涉及到线程的本地存储,也就是TLS,new对象的时候,真的是相当的羞涩啊!!
static bool gShutdown = false; static bool gHaveTLS = false; IPCThreadState* IPCThreadState::self()//调用self不是创建一个线程,而是得到当前线程的IPCThreadState对象 { if (gHaveTLS) {//第一次进来为false,所以第一次进来不会进来这里 restart: const pthread_key_t k = gTLS; /* TLS是Thread Local Storage(线程本地存储空间)的简称。 这里只需知晓:这种空间每个线程都有,而且线程间不共享这些空间。 通过pthread_getspecific/pthread_setspecific函数可以获取/设置这些空间中的内容。 从线程本地存储空间中获得保存在其中的IPCThreadState对象。 有调用pthread_getspecific的地方,肯定也有调用pthread_setspecific的地方。 */ IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k); if (st) return st; return new IPCThreadState;//new一个对象,构造函数中会调用pthread_setspecific。 } if (gShutdown) {//初始化也是false啊 #ifdef _MTK_ENG_BUILD_ IPCThreadState* st = (IPCThreadState*)pthread_getspecific(gTLS); ALOGD("IPCThreadState 0x%p, gTLS:%d gHaveTLS:%d\n", &st, gTLS, gHaveTLS); #endif ALOGW("Calling IPCThreadState::self() during shutdown is dangerous, expect a crash.\n"); return NULL; } pthread_mutex_lock(&gTLSMutex); if (!gHaveTLS) { // 函数 pthread_key_create() 用来创建线程私有数据。该函数从 TSD 池中分配一项,将其地址值赋给 key 供以后访问使用 int key_create_value = pthread_key_create(&gTLS, threadDestructor);//创建了IPCThreadState对象,实际上写法是十分晦涩的 if (key_create_value != 0) { pthread_mutex_unlock(&gTLSMutex); ALOGW("IPCThreadState::self() unable to create TLS key, expect a crash: %s\n", strerror(key_create_value)); return NULL; } gHaveTLS = true; } pthread_mutex_unlock(&gTLSMutex); goto restart;//其实goto没有我们说的那么不好,汇编代码也有很多跳转语句,关键是要用好。 }
这里根据这个描述,就不深入threadDestructor函数了。
主要用到TLS,首次进入gHaveTLS为false,锁保护说明此函数很多其他函数在调用。
通过if (pthread_key_create(&gTLS, threadDestructor) != 0),中threadDestructor(void *st)
调用IPCThreadState::IPCThreadState()创建IPCThreadState对象,并将对象的索引设置为gTLS。再次进入后通过gTLS获取到IPCThreadState对象。
IPCThreadState::IPCThreadState() : mProcess(ProcessState::self()), mMyThreadId(gettid()), mStrictModePolicy(0), mLastTransactionBinderFlags(0) { //在构造函数中,把自己设置到线程本地存储中去 pthread_setspecific(gTLS, this);//线程说,我已经藏在TLS中,下次就通过get/set来和我联系吧! clearCaller();// 初始化进程id和uid为0 //mIn和mOut是两个Parcel。把它看成是发送和接收命令的缓冲区即可。 mIn.setDataCapacity(256); mOut.setDataCapacity(256); }
3.2.2传输带:transact
这里先以添加服务为例:发送数据------>等待回应。
//注意,handle的值为0,代表了通信的目的端。 status_t IPCThreadState::transact(int32_t handle,// 传入的是0 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { status_t err = data.errorCheck();//我们传入的Parcle flags |= TF_ACCEPT_FDS;//flags初始化是0,取|后就是TF_ACCEPT_FDS //这个应该就是一个判断的log输出 IF_LOG_TRANSACTIONS() { TextOutput::Bundle _b(alog); alog << "BC_TRANSACTION thr " << (void*)pthread_self() << " / hand " << handle << " / code " << TypeCode(code) << ": " << indent << data << dedent << endl; } /* 注意这里的第一个参数BC_TRANSACTION,它是应用程序向binder设备发送消息的消息码, 而binder设备向应用程序回复消息的消息码以BR_开头。消息码的定义在 binder_module.h中,请求消息码和回应消息码的对应关系,需要查看Binder驱动的实现才能将其理清楚,我们这里暂时用不上。 */ if (err == NO_ERROR) { LOG_ONEWAY(">>>> SEND from pid %d uid %d %s", getpid(), getuid(), (flags & TF_ONE_WAY) == 0 ? "READ REPLY" : "ONE WAY"); err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);//应用程序向binder发送消息 } if (err != NO_ERROR) { if (reply) reply->setError(err); #ifdef _MTK_ENG_BUILD_ ALOGD("transact return err=%d before ioctl\n", (int32_t)err); #endif return (mLastError = err);//一个赋值语句的返回值,肯定是0啊! } if ((flags & TF_ONE_WAY) == 0) {//flag参数默认是0,这里只有前面设置为TF_ACCEPT_FDS,所以这里为true if (reply) {//reply不为空 err = waitForResponse(reply); } else { Parcel fakeReply; err = waitForResponse(&fakeReply); } IF_LOG_TRANSACTIONS() { TextOutput::Bundle _b(alog); alog << "BR_REPLY thr " << (void*)pthread_self() << " / hand "<< handle << ": "; if (reply) alog << indent << *reply << dedent << endl; else alog << "(none requested)" << endl; } } else { err = waitForResponse(NULL, NULL); } #ifdef _MTK_ENG_BUILD_ if (err != NO_ERROR) { ALOGD("transact return err=%d\n", (int32_t)err); } #endif return err; }
第一个函数发送命令请求,实际上有点名不副实:WriteTransactData()语气说是发送数据,不如说是将数据打包成binder_transact_data类型
struct binder_transaction_data { /* The first two are only used for bcTRANSACTION and brTRANSACTION, * identifying the target and contents of the transaction. */ union { size_t handle; /* target descriptor of command transaction */ //指挥交易目标描述符 void *ptr; /* target descriptor of return transaction */ // 返回交易目标描述符 } target; void *cookie; /* target object cookie */ unsigned int code; /* transaction command */ /* General information about the transaction. */ unsigned int flags; pid_t sender_pid; uid_t sender_euid; size_t data_size; /* number of bytes of data */ size_t offsets_size; /* number of bytes of offsets */ /* If this transaction is inline, the data immediately * follows here; otherwise, it ends with a pointer to * the data buffer. */ union { struct { /* transaction data */ const void *buffer; //传输内容的数据量 /* offsets from buffer to flat_binder_object structs */ const void *offsets; // Binder实体的偏移量(会遇到多个Binder实体) } ptr; uint8_t buf[8]; } data; };
具体来看看,是如何填充:
status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags, int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer)//最后一个传入的值是NULL {//binder_transaction_data是和binder设备通信的数据结构 binder_transaction_data tr; tr.target.ptr = 0; /* Don't pass uninitialized stack data to a remote process */ //果然,handle的值传递给了target,用来标识目的端,其中0是sServiceManager的标志 tr.target.handle = handle; tr.code = code;//code是消息码,是用来switch/case的! tr.flags = binderFlags; tr.cookie = 0; tr.sender_pid = 0; tr.sender_euid = 0; const status_t err = data.errorCheck(); if (err == NO_ERROR) { tr.data_size = data.ipcDataSize(); tr.data.ptr.buffer = data.ipcData(); tr.offsets_size = data.ipcObjectsCount()*sizeof(binder_size_t); tr.data.ptr.offsets = data.ipcObjects(); } else if (statusBuffer) {//第一次传入NULL的话,应该是不会进来的 tr.flags |= TF_STATUS_CODE; *statusBuffer = err; tr.data_size = sizeof(status_t); tr.data.ptr.buffer = reinterpret_cast<uintptr_t>(statusBuffer); tr.offsets_size = 0; tr.data.ptr.offsets = 0; } else { return (mLastError = err); } //把命令写到mOut中,而不是直接发出去,可见这个函数有点名不副实。我之前好像有点搞错了,mOut实际是发送数据,mIn才是接收数据 mOut.writeInt32(cmd); mOut.write(&tr, sizeof(tr)); return NO_ERROR; }
然后是等待相应:
//执行waitForResponse()方法,循环执行,直到收到应答消息. 调用talkWithDriver()跟驱动交互,收到应答消息,便会写入mIn, 则根据收到的不同响应吗,执行相应的操作。 status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)//添加服务的函数中,后一个参数是NULL { uint32_t cmd; int32_t err; #ifdef _MTK_ENG_BUILD_ cmd = 0;// initialze it for build error [-Werror=maybe-uninitialized] #endif while (1) {//好家伙,talkWithDriver! if ((err=talkWithDriver()) < NO_ERROR) //我假设是在第二次轮询的时候没有收到应答信息然后退出 break; err = mIn.errorCheck();//和binder通信完了,mIn里面已经有数据了 if (err < NO_ERROR) break; if (mIn.dataAvail() == 0) continue; cmd = (uint32_t)mIn.readInt32(); IF_LOG_COMMANDS() { alog << "Processing waitForResponse Command: "<< getReturnString(cmd) << endl; } // BR是binder设备向应用程序发送消息的消息码,和BC相互对应 // BC_XXX/BC_XXX命令对 switch (cmd) { case BR_TRANSACTION_COMPLETE: if (!reply && !acquireResult) goto finish; break; case BR_DEAD_REPLY: err = DEAD_OBJECT; goto finish; case BR_FAILED_REPLY: err = FAILED_TRANSACTION; goto finish; case BR_ACQUIRE_RESULT: { ALOG_ASSERT(acquireResult != NULL, "Unexpected brACQUIRE_RESULT"); const int32_t result = mIn.readInt32(); if (!acquireResult) continue; *acquireResult = result ? NO_ERROR : INVALID_OPERATION; } goto finish; case BR_REPLY: { binder_transaction_data tr; err = mIn.read(&tr, sizeof(tr)); ALOG_ASSERT(err == NO_ERROR, "Not enough command data for brREPLY"); if (err != NO_ERROR) goto finish; if (reply) {//reply不为NULL if ((tr.flags & TF_STATUS_CODE) == 0) { reply->ipcSetDataReference( reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer), tr.data_size, reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets), tr.offsets_size/sizeof(binder_size_t), freeBuffer, this); } else { err = *reinterpret_cast<const status_t*>(tr.data.ptr.buffer); freeBuffer(NULL, reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer), tr.data_size, reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets), tr.offsets_size/sizeof(binder_size_t), this); } } else { freeBuffer(NULL, reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer), tr.data_size, reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets), tr.offsets_size/sizeof(binder_size_t), this); continue; } } goto finish; default: // 默认返回的就是BR_TRANSACT err = executeCommand(cmd);// 执行命令 if (err != NO_ERROR) goto finish; break; } } finish: if (err != NO_ERROR) { if (acquireResult) *acquireResult = err; if (reply) reply->setError(err); mLastError = err; #ifdef _MTK_ENG_BUILD_ ALOGD("WFR got cmd %d err=%d\n", cmd, err); #endif } return err; }
BC_TRANSACT的回应者是BR_TRANSACT,所以这里直接就到了default,所以就直接到了这里面来了。
executeCommand(cmd);// 执行命令
3.2.3真正的通信者talkWithDriver
数据打包成了binder_transact_data并写入mOut之后,需要做的就是真正和binder设备通信(talkWithDriver),然后将得到返回值。
status_t IPCThreadState::talkWithDriver(bool doReceive) { if (mProcess->mDriverFD <= 0) {//打开binder设备失败 return -EBADF; } binder_write_read bwr;//binder_write_read是用来与binder设备交换数据的结构。 // Is the read buffer empty? const bool needRead = mIn.dataPosition() >= mIn.dataSize(); // We don't want to write anything if we are still reading // from data left in the input buffer and the caller // has requested to read the next data. const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0; //请求命令的填充。 bwr.write_size = outAvail; bwr.write_buffer = (uintptr_t)mOut.data();// (uintptr_t)类型存放的是指针地址 // This is what we'll read. //接收数据缓冲区信息的填充。如果以后收到数据,就直接填在mIn中了。 if (doReceive && needRead) { bwr.read_size = mIn.dataCapacity(); bwr.read_buffer = (uintptr_t)mIn.data();//(uintptr_t)类型存放的是指针地址 } else {//mOut有数据,mIn还没有数据。doReceive默认值为true bwr.read_size = 0; bwr.read_buffer = 0; } // 都属于是log输出 IF_LOG_COMMANDS() { TextOutput::Bundle _b(alog); if (outAvail != 0) { alog << "Sending commands to driver: " << indent; const void* cmds = (const void*)bwr.write_buffer; const void* end = ((const uint8_t*)cmds)+bwr.write_size; alog << HexDump(cmds, bwr.write_size) << endl; while (cmds < end) cmds = printCommand(alog, cmds); alog << dedent; } alog << "Size of receive buffer: " << bwr.read_size << ", needRead: " << needRead << ", doReceive: " << doReceive << endl; } // Return immediately if there is nothing to do. if ((bwr.write_size == 0) && (bwr.read_size == 0)) return NO_ERROR; bwr.write_consumed = 0; bwr.read_consumed = 0; status_t err; //中间东西太复杂了,不就是把mOut数据和mIn接收数据的处理后赋值给bwr吗? do { IF_LOG_COMMANDS() { alog << "About to read/write, write size = " << mOut.dataSize() << endl; } #if defined(__ANDROID__) //看来不是read/write调用,而是ioctl方式。 if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0) err = NO_ERROR; else { #ifdef _MTK_ENG_BUILD_ ALOGD("TWD: ioctl return errno %d\n", errno); #endif err = -errno; } #else err = INVALID_OPERATION; #endif if (mProcess->mDriverFD <= 0) {//主要是对于多次轮询的时候做判断 err = -EBADF; } IF_LOG_COMMANDS() { alog << "Finished read/write, write size = " << mOut.dataSize() << endl; } } while (err == -EINTR); IF_LOG_COMMANDS() { alog << "Our err: " << (void*)(intptr_t)err << ", write consumed: " << bwr.write_consumed << " (of " << mOut.dataSize() << "), read consumed: " << bwr.read_consumed << endl; } // 这个先不关注 if (err >= NO_ERROR) { if (bwr.write_consumed > 0) { if (bwr.write_consumed < mOut.dataSize()) mOut.remove(0, bwr.write_consumed); else mOut.setDataSize(0); } if (bwr.read_consumed > 0) { mIn.setDataSize(bwr.read_consumed); mIn.setDataPosition(0); } IF_LOG_COMMANDS() { TextOutput::Bundle _b(alog); alog << "Remaining data size: " << mOut.dataSize() << endl; alog << "Received commands from driver: " << indent; const void* cmds = mIn.data(); const void* end = mIn.data() + mIn.dataSize(); alog << HexDump(cmds, mIn.dataSize()) << endl; while (cmds < end) cmds = printReturnCommand(alog, cmds); alog << dedent; } return NO_ERROR; } return err; }
4、开启线程池startThreadpool
void ProcessState::startThreadPool() { AutoMutex _l(mLock); if (!mThreadPoolStarted) { mThreadPoolStarted = true; spawnPooledThread(true);//注意,传进去的参数是true。 } }
里面解决一个之前在inputreader和dispatcher里面的疑惑,为什么run执行完之后会循环执行threadloop
void ProcessState::spawnPooledThread(bool isMain) { //PoolThread是在IPCThreadState中定义的一个Thread子类 if (mThreadPoolStarted) {// 放俺进去,刚刚朕已经给了一个true了 String8 name = makeBinderThreadName();//大胆猜测是“media.drm” ALOGV("Spawning new pooled thread, name=%s\n", name.string()); sp<Thread> t = new PoolThread(isMain); t->run(name.string());//会循环执行threadloop吗?实际上是不会的,因为在threadloop里面返回了false } }
Thread被创建,
Thread中的run被调用,
__threadLoop()被调用,
readyToRun()被调用,
然后循环调用threadLoop()。
并且在threadLoop()返回false时,可以退出循环。这个和inputdispatcher或者说InputReader不一样的是,这里是返回false,而输入子系统那块是返回true。具体的有空可以去分析。
class PoolThread : public Thread { public: PoolThread(bool isMain) : mIsMain(isMain)//为true了 { } protected: virtual bool threadLoop()//只会执行一次 {//线程函数如此简单,不过是在这个新线程中又创建了一个IPCThreadState。 //你还记得它是每个伙计都有一个的吗? IPCThreadState* ipc = IPCThreadState::self(); if(ipc) ipc->joinThreadPool(mIsMain);//新建立的线程添加到线程池里面去,怎么区分一个是新建线程,一个是主线程呢?妈呀!这个变量不是说了吗?mIsMain //IPCThreadState::self()->joinThreadPool(mIsMain); return false; } const bool mIsMain;// 初始化为true };
实际上是创建了一个主线程。并将主线程加入线程池。
void IPCThreadState::joinThreadPool(bool isMain)//主线程是没有往里面扔数据的,因为主线程里面模式是没有传入参数的 { LOG_THREADPOOL("**** THREAD %p (PID %d) IS JOINING THE THREAD POOL\n", (void*)pthread_self(), getpid()); // 注意,如果isMain为true,我们则需要循环处理。把请求信息写到mOut中,待会儿一起发出去。mOut实际上是全局的 /* 对于isMain=true的情况下, command为BC_ENTER_LOOPER,代表的是Binder主线程,不会退出的线程; 对于isMain=false的情况下,command为BC_REGISTER_LOOPER,表示是由binder驱动创建的线程。 */ mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER); // This thread may have been spawned by a thread that was in the background // scheduling group, so first we will make sure it is in the foreground // one to avoid performing an initial transaction in the background. set_sched_policy(mMyThreadId, SP_FOREGROUND);// 设置哪个线程为前台线程呢?mMyThreadId是在构建IPCThreadState的时候更新的 // 主线程调用该函数的时候就是主线程,新建的线程调用的时候就是新建的线程调用的 status_t result; do {//这个是很重要的,意味着,他实际上是在循环监听着客户端通过binder_driver来发送的请求,之前一直忽视,导致一直费解 processPendingDerefs();// 处理上次循环尚未完成的内容 // now get the next command to be processed, waiting if necessary result = getAndExecuteCommand(); if (result < NO_ERROR && result != TIMED_OUT && result != -ECONNREFUSED && result != -EBADF) { ALOGE("getAndExecuteCommand(fd=%d) returned unexpected error %d, aborting", mProcess->mDriverFD, result); abort(); //退出线程 } // Let this thread exit the thread pool if it is no longer // needed and it is not the main process thread. if(result == TIMED_OUT && !isMain) {//也是退出线程,只是前者是强制退出,后者是执行结束后退出 break; } } while (result != -ECONNREFUSED && result != -EBADF); LOG_THREADPOOL("**** THREAD %p (PID %d) IS LEAVING THE THREAD POOL err=%p\n", (void*)pthread_self(), getpid(), (void*)result); mOut.writeInt32(BC_EXIT_LOOPER); talkWithDriver(false);//和底层驱动交互 }
来看看getAndExecuteCommand
status_t IPCThreadState::getAndExecuteCommand() { status_t result; int32_t cmd; //发送命令,读取请求 result = talkWithDriver();//循环和binder_driver进行交流,获取客户端的请求,然后再对请求进行处理excutecommand if (result >= NO_ERROR) { size_t IN = mIn.dataAvail();//mIn应该也是全局的 if (IN < sizeof(int32_t)) // 应该一般都不会执行到这里 return result; cmd = mIn.readInt32(); IF_LOG_COMMANDS() {alog << "Processing top-level Command: "<< getReturnString(cmd) << endl;} pthread_mutex_lock(&mProcess->mThreadCountLock);//先不管mProcess,这里只要知道那是一个上锁的地方就OK了 mProcess->mExecutingThreadsCount++;//自增 if (mProcess->mExecutingThreadsCount >= mProcess->mMaxThreads &&mProcess->mStarvationStartTimeMs == 0) { mProcess->mStarvationStartTimeMs = uptimeMillis(); } pthread_mutex_unlock(&mProcess->mThreadCountLock); result = executeCommand(cmd);//处理消息 pthread_mutex_lock(&mProcess->mThreadCountLock); mProcess->mExecutingThreadsCount--;//自减,这样的话就保持不变 if (mProcess->mExecutingThreadsCount < mProcess->mMaxThreads &&mProcess->mStarvationStartTimeMs != 0) { int64_t starvationTimeMs = uptimeMillis() - mProcess->mStarvationStartTimeMs; if (starvationTimeMs > 100) { ALOGE("binder thread pool (%zu threads) starved for %" PRId64 " ms", mProcess->mMaxThreads, starvationTimeMs); } mProcess->mStarvationStartTimeMs = 0; } // 会重启动等待该条件变量的所有线程 pthread_cond_broadcast(&mProcess->mThreadCountDecrement); pthread_mutex_unlock(&mProcess->mThreadCountLock); set_sched_policy(mMyThreadId, SP_FOREGROUND);// 防止其他调用,将其设置成了后台线程 } return result; }
然后是excutemand函数,这个在客户端这个有介绍:
status_t IPCThreadState:: executeCommand(int32_t cmd) { BBinder* obj; RefBase::weakref_type* refs; status_t result = NO_ERROR; switch ((uint32_t)cmd) { case BR_ERROR: result = mIn.readInt32(); break; case BR_OK: break; case BR_ACQUIRE: refs = (RefBase::weakref_type*)mIn.readPointer(); obj = (BBinder*)mIn.readPointer(); ALOG_ASSERT(refs->refBase() == obj, "BR_ACQUIRE: object %p does not match cookie %p (expected %p)", refs, obj, refs->refBase()); obj->incStrong(mProcess.get()); IF_LOG_REMOTEREFS() { LOG_REMOTEREFS("BR_ACQUIRE from driver on %p", obj); obj->printRefs(); } mOut.writeInt32(BC_ACQUIRE_DONE); mOut.writePointer((uintptr_t)refs); mOut.writePointer((uintptr_t)obj); break; case BR_RELEASE: refs = (RefBase::weakref_type*)mIn.readPointer(); obj = (BBinder*)mIn.readPointer(); ALOG_ASSERT(refs->refBase() == obj, "BR_RELEASE: object %p does not match cookie %p (expected %p)", refs, obj, refs->refBase()); IF_LOG_REMOTEREFS() { LOG_REMOTEREFS("BR_RELEASE from driver on %p", obj); obj->printRefs(); } mPendingStrongDerefs.push(obj); break; case BR_INCREFS: refs = (RefBase::weakref_type*)mIn.readPointer(); obj = (BBinder*)mIn.readPointer(); refs->incWeak(mProcess.get()); mOut.writeInt32(BC_INCREFS_DONE); mOut.writePointer((uintptr_t)refs); mOut.writePointer((uintptr_t)obj); break; case BR_DECREFS: refs = (RefBase::weakref_type*)mIn.readPointer(); obj = (BBinder*)mIn.readPointer(); mPendingWeakDerefs.push(refs); break; case BR_ATTEMPT_ACQUIRE: refs = (RefBase::weakref_type*)mIn.readPointer(); obj = (BBinder*)mIn.readPointer(); { const bool success = refs->attemptIncStrong(mProcess.get()); ALOG_ASSERT(success && refs->refBase() == obj, "BR_ATTEMPT_ACQUIRE: object %p does not match cookie %p (expected %p)", refs, obj, refs->refBase()); mOut.writeInt32(BC_ACQUIRE_RESULT); mOut.writeInt32((int32_t)success); } break; case BR_TRANSACTION: { binder_transaction_data tr; result = mIn.read(&tr, sizeof(tr)); ALOG_ASSERT(result == NO_ERROR, "Not enough command data for brTRANSACTION"); if (result != NO_ERROR) break; Parcel buffer; Parcel buffer; buffer.ipcSetDataReference( reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer), tr.data_size, reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets), tr.offsets_size/sizeof(binder_size_t), freeBuffer, this); const pid_t origPid = mCallingPid; const uid_t origUid = mCallingUid; const int32_t origStrictModePolicy = mStrictModePolicy; const int32_t origTransactionBinderFlags = mLastTransactionBinderFlags; mCallingPid = tr.sender_pid; mCallingUid = tr.sender_euid; mLastTransactionBinderFlags = tr.flags; int curPrio = getpriority(PRIO_PROCESS, mMyThreadId); if (gDisableBackgroundScheduling) { if (curPrio > ANDROID_PRIORITY_NORMAL) { setpriority(PRIO_PROCESS, mMyThreadId, ANDROID_PRIORITY_NORMAL); } } else { if (curPrio >= ANDROID_PRIORITY_BACKGROUND) { set_sched_policy(mMyThreadId, SP_BACKGROUND); } } //ALOGI(">>>> TRANSACT from pid %d uid %d\n", mCallingPid, mCallingUid); Parcel reply; status_t error; IF_LOG_TRANSACTIONS() { alog << "BR_TRANSACTION thr " << (void*)pthread_self() << " / obj " << tr.target.ptr << " / code " << TypeCode(tr.code) << ": " << indent << buffer << dedent << endl << "Data addr = " << reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer) << ", offsets addr=" << reinterpret_cast<const size_t*>(tr.data.ptr.offsets) << endl; } if (tr.target.ptr) { if (reinterpret_cast<RefBase::weakref_type*>( tr.target.ptr)->attemptIncStrong(this)) { error = reinterpret_cast<BBinder*>(tr.cookie)->transact(tr.code, buffer, &reply, tr.flags); reinterpret_cast<BBinder*>(tr.cookie)->decStrong(this); } else { error = UNKNOWN_TRANSACTION; } } else { // the_context_object实际上是一个全局变量,实际上他是一个BBinder的对象 error = the_context_object->transact(tr.code, buffer, &reply, tr.flags); } //ALOGI("<<<< TRANSACT from pid %d restore pid %d uid %d\n", // mCallingPid, origPid, origUid); if ((tr.flags & TF_ONE_WAY) == 0) { LOG_ONEWAY("Sending reply to %d!", mCallingPid); if (error < NO_ERROR) reply.setError(error); sendReply(reply, 0); } else { LOG_ONEWAY("NOT sending reply to %d!", mCallingPid); } mCallingPid = origPid; mCallingUid = origUid; mStrictModePolicy = origStrictModePolicy; mLastTransactionBinderFlags = origTransactionBinderFlags; IF_LOG_TRANSACTIONS() { TextOutput::Bundle _b(alog); alog << "BC_REPLY thr " << (void*)pthread_self() << " / obj " << tr.target.ptr << ": " << indent << reply << dedent << endl; } } break; break; /*收到Binder驱动发来的service死掉的消息,看来只有Bp端能收到了,后面我们将会对此进行分析。*/ //Binder驱动会通知死亡消息 case BR_DEAD_BINDER: { BpBinder *proxy = (BpBinder*)mIn.readPointer();//下面的proxy对应着已经死亡的远端BBinder。 #ifdef _MTK_ENG_BUILD_ ALOGD("[DN #5] BR_DEAD_BINDER cookie %p", proxy); #endif proxy->sendObituary();//发送讣告,Obituary是讣告的意思。最终会传递到你的DeathNotifier中。 mOut.writeInt32(BC_DEAD_BINDER_DONE); mOut.writePointer((uintptr_t)proxy); } break; case BR_CLEAR_DEATH_NOTIFICATION_DONE: { BpBinder *proxy = (BpBinder*)mIn.readPointer(); proxy->getWeakRefs()->decWeak(proxy); } break; case BR_FINISHED: result = TIMED_OUT; break; case BR_NOOP: break; //特别注意,这里将收到来自驱动的指示以创建一个新线程,用于和Binder通信 case BR_SPAWN_LOOPER: mProcess->spawnPooledThread(false); break; default: #ifdef _MTK_ENG_BUILD_ ALOGD("*** BAD COMMAND %d received from Binder driver\n", cmd); #else printf("*** BAD COMMAND %d received from Binder driver\n", cmd); #endif result = UNKNOWN_ERROR; break; } if (result != NO_ERROR) { #ifdef _MTK_ENG_BUILD_ ALOGD("EXECMD cmd %d return %d\n", cmd, (int32_t)result); #endif mLastError = result; } return result; }
BBinder的transact函数里面会调用它的子类的ontrasact函数。
5、将当前线程添加到线程池jionThreadPool
IPCThreadState::self()->joinThreadPool();
有好几次调用IPCThreadState::self()难道每次调用都产生了一条线程,那是得产生多少条线程啊!实际上不是的,具体的详见上面的self函数的分析
总结:
int main() { // 这个我肯定是在surfaceflinger里面见到过的,且里面的套路是一样的,ProcessState,实际上每个进程只有一个对象,就像是每个进程有唯一的javaVM一样 signal(SIGPIPE, SIG_IGN); // 1、获取ProcessState实例,实际上这里的self表示的是单例模式 sp<ProcessState> proc(ProcessState::self()); // 2、sm作为ServiceManager的客户端,需要向ServiceManager注册服务,调用defaultServiceManager,得到一个IServiceManager sp<IServiceManager> sm = defaultServiceManager(); ALOGI("ServiceManager: %p", sm.get()); // 3、初始化多媒体系统的MediaPlayer服务,我们将以它作为主切入点 MediaDrmService::instantiate(); // 4、根据名称来推断,难道是要创建一个线程池吗? ProcessState::self()->startThreadPool();//startThreadPool中新启动的线程通过joinThreadPool读取binder设备,查看是否有请求(这个才是主线程吗?) // 5、将自己加入到刚才的线程池中 IPCThreadState::self()->joinThreadPool();//主线程也调用joinThreadPool读取binder设备,查看是否有请求(当前线程?) }