手写一个C++ Android Binder服务及源码分析
手写一个C++ Android Binder服务及源码分析
- 前言
- 一、 基于C语言编写Android Binder跨进程通信Demo总结及改进
- 二、C++语言编写自己的Binder服务Demo
- 1. binder服务demo功能介绍
- 2. binder服务demo代码结构图
- 3. binder服务demo代码实现
- 3.1 IHelloService.h代码实现
- 3.2 BnHelloService.cpp代码实现
- 3.3 BpHelloService.cpp代码实现
- 3.4 test_server.cpp代码实现
- 3.5 test_client.cpp代码实现
- 3.6 编译binder服务的Android.mk文件
- 三、C++编写的Binder服务Demo源码解析
- 1. test_client.cpp源码解析
- 1.1 分析如何获得BpServiceManager对象
- 1.2 分析如何获得BpHelloServie对象
- 1.3 代理类如何发送数据?
- 2. test_server.cpp源码解析
- 2.1 分析数据传输机制ProcessState和IPCThreadState
- 2.2 分析向servicemanager添加服务的具体过程
- 2.3 分析server如何分辨client想使用哪一个服务,并调用对应的函数
前言
之前我写了三篇文章深入内核讲明白Android Binder,这三篇文章可以理解为是Android Binder的原理篇,本篇文章算是应用篇,讲明白如何使用C++语言编写自己的binder服务(C++只是利用语言优势,更好的封装了C语言实现的Android binder,方便开发人员使用binder),并深入源码搞清楚C++编写binder服务的逻辑。
深入内核讲明白Android Binder【一】
深入内核讲明白Android Binder【二】
深入内核讲明白Android Binder【三】
阅读建议:
- 如果有余力建议去阅读下我之前写的三篇【深入内核讲明白Android Binder】系列的文章,这三篇文章深入linux内核解析android binder源码,如果搞清楚了这三篇文章,再来看这篇使用C++应用Android binder的文章就非常容易理解。
- 如果直接看这篇文章也是可以的,但这篇文章只能使您停留在会使用C++语言编写自己的Android binder服务的层面上。
一、 基于C语言编写Android Binder跨进程通信Demo总结及改进
深入内核讲明白Android Binder【一】我们讲解了如何使用C语言编写自己的binder服务,但所有代码都写在一个c文件中。职责不够分明,代码不易重用,也不利于代码阅读和维护。
我们可以把上面的结构优化下面的结构,即定义一个头文件IHelloService.h包含服务端和客户端共用的函数接口,BnHelloService和BpHelloService充当代理,分别实现客户端和服务端的功能,分别供binder服务test_server和客户端test_client.c使用。而这也是C++语言编写binder服务的整体框架。
二、C++语言编写自己的Binder服务Demo
1. binder服务demo功能介绍
我们继续采用深入内核讲明白Android Binder【一】中C语言实现的binder服务功能。C++实现的binder服务也提供sayhello和sayhello_to两个函数供客户端调用。
2. binder服务demo代码结构图
- IHelloService.h:定义服务端和客户端共用的接口类。
- BnHelloService.cpp:服务端的代理类。BnHelloService类的具体实现(binder服务的本地实现)
- BpHelloService.cpp:客户端的代理类。文件中定义BpHelloService类,继承IHelloService(客户端调用binder服务的实现)
- test_server.cpp:binder服务提供者(服务端)
- test_client.cpp:binder服务使用者(客户端)
3. binder服务demo代码实现
3.1 IHelloService.h代码实现
- 参考代码:frameworks\av\include\media\IMediaPlayerService.h
定义接口类IHelloService,类中有sayhello,sayhello_to两个纯虚函数。BnHelloService类和BpHelloService类会继承IHelloService实现这两个虚函数。
/* 参考: frameworks\av\include\media\IMediaPlayerService.h */
#ifndef ANDROID_IHELLOERVICE_H
#define ANDROID_IHELLOERVICE_H
#include <utils/Errors.h> // for status_t
#include <utils/KeyedVector.h>
#include <utils/RefBase.h>
#include <utils/String8.h>
#include <binder/IInterface.h>
#include <binder/Parcel.h>
#define HELLO_SVR_CMD_SAYHELLO 1
#define HELLO_SVR_CMD_SAYHELLO_TO 2
#define HELLO_SVR_CMD_GET_FD 3
namespace android {
class IHelloService: public IInterface
{
public:
//声明接口
DECLARE_META_INTERFACE(HelloService);
virtual void sayhello(void) = 0;
virtual int sayhello_to(const char *name) = 0;
};
//继承自IHelloService和BBinder
class BnHelloService: public BnInterface<IHelloService>
{
public:
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
virtual void sayhello(void);
virtual int sayhello_to(const char *name);
BnHelloService();
};
}
//https://github.com/CyanogenMod/android_frameworks_native/blob/cm-14.1/include/binder/IInterface.h
template<typename INTERFACE>
class BnInterface : public INTERFACE, public BBinder
{
public:
virtual sp<IInterface> queryLocalInterface(const String16& _descriptor);
virtual const String16& getInterfaceDescriptor() const;
typedef INTERFACE BaseInterface;
protected:
virtual IBinder* onAsBinder();
};
//通过预处理器运算符##(标记粘合符),声明接口
#define DECLARE_META_INTERFACE(INTERFACE) \
static const android::String16 descriptor; \
static android::sp<I##INTERFACE> asInterface( \
const android::sp<android::IBinder>& obj); \
virtual const android::String16& getInterfaceDescriptor() const; \
I##INTERFACE(); \
virtual ~I##INTERFACE();
3.2 BnHelloService.cpp代码实现
- 参考代码:frameworks\av\media\libmedia\IMediaPlayerService.cpp
BnHelloService作为服务端的代理类,是binder服务的本地实现
/* 参考: frameworks\av\media\libmedia\IMediaPlayerService.cpp */
#define LOG_TAG "HelloService"
#include "IHelloService.h"
namespace android {
BnHelloService::BnHelloService()
{
}
// 根据code,确定调用服务的哪一个函数
status_t BnHelloService::onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags)
{
/* 解析数据,调用sayhello/sayhello_to */
switch (code) {
case HELLO_SVR_CMD_SAYHELLO: {
sayhello();
reply->writeInt32(0); /* no exception */
return NO_ERROR;
} break;
case HELLO_SVR_CMD_SAYHELLO_TO: {
/* 从data中取出参数 */
int32_t policy = data.readInt32();
String16 name16_tmp = data.readString16(); /* IHelloService */
String16 name16 = data.readString16();
String8 name8(name16);
int cnt = sayhello_to(name8.string());
/* 把返回值写入reply传回去 */
reply->writeInt32(0); /* no exception */
reply->writeInt32(cnt);
return NO_ERROR;
} break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
}
void BnHelloService::sayhello(void)
{
static int cnt = 0;
ALOGI("say hello : %d\n", ++cnt);
}
int BnHelloService::sayhello_to(const char *name)
{
static int cnt = 0;
ALOGI("say hello to %s : %d\n", name, ++cnt);
return cnt;
}
}
3.3 BpHelloService.cpp代码实现
- 参考代码:frameworks\av\media\libmedia\IMediaPlayerService.cpp
BpHelloService作为客户端的代理类,是客户端调用binder服务的具体实现。
客户端调用服务端函数的步骤:1. 构造数据;2. 向服务端发送数据;3. 获取服务端返回的数据
/* 参考: frameworks\av\media\libmedia\IMediaPlayerService.cpp */
#include "IHelloService.h"
namespace android {
//继承自IHelloService和BpRefBase
class BpHelloService: public BpInterface<IHelloService>
{
public:
BpHelloService(const sp<IBinder>& impl)
: BpInterface<IHelloService>(impl)
{
}
void sayhello(void)
{
/* 构造/发送数据 */
Parcel data, reply;
//为了与C实现的binder兼容,需要把传入的数据格式与C读取的数据格式一致
data.writeInt32(0);
data.writeString16(String16("IHelloService"));
// 发送数据
remote()->transact(HELLO_SVR_CMD_SAYHELLO, data, &reply);
}
int sayhello_to(const char *name)
{
/* 构造/发送数据 */
Parcel data, reply;
int exception;
data.writeInt32(0);
data.writeString16(String16("IHelloService"));
data.writeString16(String16(name));
// 发送数据
remote()->transact(HELLO_SVR_CMD_SAYHELLO_TO, data, &reply);
// 获得服务返回的数据
exception = reply.readInt32();
if (exception)
return -1;
else
return reply.readInt32();
}
};
// 实现接口
IMPLEMENT_META_INTERFACE(HelloService, "android.media.IHelloService");
}
//https://github.com/CyanogenMod/android_frameworks_native/blob/cm-14.1/include/binder/IInterface.h
template<typename INTERFACE>
class BpInterface : public INTERFACE, public BpRefBase
{
public:
explicit BpInterface(const sp<IBinder>& remote);
typedef INTERFACE BaseInterface;
protected:
virtual IBinder* onAsBinder();
};
//通过预处理器运算符##(标记粘合符),实现接口
#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME) \
const android::String16 I##INTERFACE::descriptor(NAME); \
const android::String16& \
I##INTERFACE::getInterfaceDescriptor() const { \
return I##INTERFACE::descriptor; \
} \
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) { \
intr = new Bp##INTERFACE(obj); \
} \
} \
return intr; \
} \
I##INTERFACE::I##INTERFACE() { } \
I##INTERFACE::~I##INTERFACE() { }
3.4 test_server.cpp代码实现
- 参考代码:frameworks\av\media\mideaserver/main_mediaserver.cpp
test_server是binder服务提供者(服务端),核心步骤:
- 打开驱动
- 获取servicemanager
- 向servicemanager中添加服务
- 死循环等待客户端发来数据,并进行处理和回复
/* 参考: frameworks\av\media\mediaserver\Main_mediaserver.cpp */
#define LOG_TAG "TestService"
//#define LOG_NDEBUG 0
#include <fcntl.h>
#include <sys/prctl.h>
#include <sys/wait.h>
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include <cutils/properties.h>
#include <utils/Log.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/socket.h>
#include "IHelloService.h"
#include "IGoodbyeService.h"
#define SOCKET_BUFFER_SIZE (32768U)
using namespace android;
/* usage : test_server */
int main(void)
{
/* 打开驱动, mmap */
sp<ProcessState> proc(ProcessState::self());
/* 获得BpServiceManager (servicemanager的代理类)*/
sp<IServiceManager> sm = defaultServiceManager();
/* 添加服务 */
sm->addService(String16("hello"), new BnHelloService(sockets[1]));
/* 循环体 */
ProcessState::self()->startThreadPool(); // 创建子线程,死循环等待客户端发送来的数据
IPCThreadState::self()->joinThreadPool(); // 创建主线程,死循环等待客户端发送来的数据
return 0;
}
3.5 test_client.cpp代码实现
- 参考代码:frameworks\av\media\mideaserver/main_mediaserver.cpp
test_client是binder服务使用者(客户端),实现核心步骤:
- 打开驱动
- 获得servicemanager
- 从servicemanager获得服务
- 调用服务的函数
#define LOG_TAG "TestService"
//#define LOG_NDEBUG 0
#include <fcntl.h>
#include <sys/prctl.h>
#include <sys/wait.h>
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include <cutils/properties.h>
#include <utils/Log.h>
#include <unistd.h>
#include "IHelloService.h"
#include "IGoodbyeService.h"
using namespace android;
/* ./test_client <hello>
* ./test_client <hello> <name>
*/
int main(int argc, char **argv)
{
int cnt;
if (argc < 2){
ALOGI("Usage:\n");
ALOGI("%s <readfile>\n", argv[0]);
ALOGI("%s <hello|goodbye>\n", argv[0]);
ALOGI("%s <hello|goodbye> <name>\n", argv[0]);
return -1;
}
/* getService */
/* 打开驱动, mmap */
sp<ProcessState> proc(ProcessState::self());
/* 获得BpServiceManager (servicemanager的代理类) */
sp<IServiceManager> sm = defaultServiceManager();
if (strcmp(argv[1], "hello") == 0)
{
sp<IBinder> binder =
sm->getService(String16("hello"));
if (binder == 0)
{
ALOGI("can't get hello service\n");
return -1;
}
/* service肯定是BpHelloServie指针 */
sp<IHelloService> service =
interface_cast<IHelloService>(binder);
/* 调用Service的函数 */
if (argc < 3) {
service->sayhello();
ALOGI("client call sayhello");
}
else {
cnt = service->sayhello_to(argv[2]);
ALOGI("client call sayhello_to, cnt = %d", cnt);
}
}
return 0;
}
3.6 编译binder服务的Android.mk文件
- 参考代码:frameworks\av\media\mideaserver/Android.mk
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
BnHelloService.cpp \
BpHelloService.cpp \
BnGoodbyeService.cpp \
BpGoodbyeService.cpp \
test_server.cpp
LOCAL_SHARED_LIBRARIES := \
libcutils \
libutils \
liblog \
libbinder
LOCAL_MODULE:= test_server
LOCAL_32_BIT_ONLY := true
include $(BUILD_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
BpHelloService.cpp \
BpGoodbyeService.cpp \
test_client.cpp
LOCAL_SHARED_LIBRARIES := \
libcutils \
libutils \
liblog \
libbinder
LOCAL_MODULE:= test_client
LOCAL_32_BIT_ONLY := true
include $(BUILD_EXECUTABLE
三、C++编写的Binder服务Demo源码解析
一图简单回顾下【深入内核讲明白Android Binder】系列的文章中讲解的Binder跨进程通信。
1. test_client.cpp源码解析
1.1 分析如何获得BpServiceManager对象
BpServiceManager是servicemanager服务的代理对象,通过BpServiceManager调用servicemanager提供的服务函数,BpServiceManager源码链接IServiceManager.cpp,BpServiceManager继承关系图如下
BpServiceManager继承自IServiceManager和BpRefBase,而BpRefBase中的mRemote成员指向BpBinder对象,BpBinder中mHandle成员代表了服务的句柄,通过mHandle可以获取相应的服务。
//继承自IServiceManager和BpRefBase
class BpServiceManager : public BpInterface<IServiceManager>
{
public:
BpServiceManager(const sp<IBinder>& impl)
: BpInterface<IServiceManager>(impl)
{
}
virtual sp<IBinder> getService(const String16& name) const
{
unsigned n;
for (n = 0; n < 5; n++){
sp<IBinder> svc = checkService(name);
if (svc != NULL) return svc;
ALOGI("Waiting for service %s...\n", String8(name).string());
sleep(1);
}
return NULL;
}
virtual sp<IBinder> checkService( const String16& name) const
{
Parcel data, reply;
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeString16(name);
remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply);
return reply.readStrongBinder();
}
virtual status_t addService(const String16& name, const sp<IBinder>& service,
bool allowIsolated)
{
Parcel data, reply;
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeString16(name);
data.writeStrongBinder(service);
data.writeInt32(allowIsolated ? 1 : 0);
status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
return err == NO_ERROR ? reply.readExceptionCode() : err;
}
virtual Vector<String16> listServices()
{
Vector<String16> res;
int n = 0;
for (;;) {
Parcel data, reply;
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeInt32(n++);
status_t err = remote()->transact(LIST_SERVICES_TRANSACTION, data, &reply);
if (err != NO_ERROR)
break;
res.add(reply.readString16());
}
return res;
}
};
IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");
}; // namespace android
class BpRefBase : public virtual RefBase
{
protected:
BpRefBase(const sp<IBinder>& o);
virtual ~BpRefBase();
virtual void onFirstRef();
virtual void onLastStrongRef(const void* id);
virtual bool onIncStrongAttempted(uint32_t flags, const void* id);
inline IBinder* remote() { return mRemote; }
inline IBinder* remote() const { return mRemote; }
private:
BpRefBase(const BpRefBase& o);
BpRefBase& operator=(const BpRefBase& o);
IBinder* const mRemote;//指向BpBinder对象
RefBase::weakref_type* mRefs;
std::atomic<int32_t> mState;
};
}; // namespace android
class BpBinder : public IBinder
{
public:
BpBinder(int32_t handle);
inline int32_t handle() const { return mHandle; }
virtual const String16& getInterfaceDescriptor() const;
virtual bool isBinderAlive() const;
virtual status_t pingBinder();
virtual status_t dump(int fd, const Vector<String16>& args);
virtual status_t transact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
virtual status_t linkToDeath(const sp<DeathRecipient>& recipient,
void* cookie = NULL,
uint32_t flags = 0);
virtual status_t unlinkToDeath( const wp<DeathRecipient>& recipient,
void* cookie = NULL,
uint32_t flags = 0,
wp<DeathRecipient>* outRecipient = NULL);
virtual void attachObject( const void* objectID,
void* object,
void* cleanupCookie,
object_cleanup_func func);
virtual void* findObject(const void* objectID) const;
virtual void detachObject(const void* objectID);
virtual BpBinder* remoteBinder();
status_t setConstantData(const void* data, size_t size);
void sendObituary();
class ObjectManager
{
public:
ObjectManager();
~ObjectManager();
void attach( const void* objectID,
void* object,
void* cleanupCookie,
IBinder::object_cleanup_func func);
void* find(const void* objectID) const;
void detach(const void* objectID);
void kill();
private:
ObjectManager(const ObjectManager&);
ObjectManager& operator=(const ObjectManager&);
struct entry_t
{
void* object;
void* cleanupCookie;
IBinder::object_cleanup_func func;
};
KeyedVector<const void*, entry_t> mObjects;
};
protected:
virtual ~BpBinder();
virtual void onFirstRef();
virtual void onLastStrongRef(const void* id);
virtual bool onIncStrongAttempted(uint32_t flags, const void* id);
private:
const int32_t mHandle;//最核心的数据
struct Obituary {
wp<DeathRecipient> recipient;
void* cookie;
uint32_t flags;
};
void reportOneDeath(const Obituary& obit);
bool isDescriptorCached() const;
mutable Mutex mLock;
volatile int32_t mAlive;
volatile int32_t mObitsSent;
Vector<Obituary>* mObituaries;
ObjectManager mObjects;
Parcel* mConstantData;
mutable String16 mDescriptorCache;
};
之前实现的C++Demo中可知我们是通过defaultServiceManager函数获得BpServiceManager
/* usage : test_server */
int main(void)
{
/* 打开驱动, mmap */
sp<ProcessState> proc(ProcessState::self());
/* 获得BpServiceManager */
sp<IServiceManager> sm = defaultServiceManager();
sm->addService(String16("hello"), new BnHelloService(sockets[1]));
sm->addService(String16("goodbye"), new BnGoodbyeService());
/* 循环体 */
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
return 0;
}
defaultServiceManager方法源码地址defaultServiceManager()
//IServiceManager.cpp
sp<IServiceManager> defaultServiceManager()
{
//单例模式
if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
{
AutoMutex _l(gDefaultServiceManagerLock);
while (gDefaultServiceManager == NULL) {
//把BpBinder(mHandle=0)对象转换为IServiceManager接口(BpServiceManager)
gDefaultServiceManager = interface_cast<IServiceManager>(
ProcessState::self()->getContextObject(NULL));
if (gDefaultServiceManager == NULL)
sleep(1);
}
}
return gDefaultServiceManager;
}
//sp是一个智能指针类,当没有任何引用指向 `IServiceManager` 实例时,它会自动被销毁。
sp<IServiceManager> gDefaultServiceManager;
ProcessState::self()->getContextObject(NULL))获得BpBinder对象, new BpBinder(0)
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
return getStrongProxyForHandle(0);
}
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
sp<IBinder> result;
AutoMutex _l(mLock);
handle_entry* e = lookupHandleLocked(handle);
if (e != NULL) {
// We need to create a new BpBinder if there isn't currently one, OR we
// are unable to acquire a weak reference on this current one. See comment
// in getWeakProxyForHandle() for more info about this.
IBinder* b = e->binder;
if (b == NULL || !e->refs->attemptIncWeak(this)) {
if (handle == 0) {
// Special case for context manager...
// The context manager is the only object for which we create
// a BpBinder proxy without already holding a reference.
// Perform a dummy transaction to ensure the context manager
// is registered before we create the first local reference
// to it (which will occur when creating the BpBinder).
// If a local reference is created for the BpBinder when the
// context manager is not present, the driver will fail to
// provide a reference to the context manager, but the
// driver API does not return status.
//
// Note that this is not race-free if the context manager
// dies while this code runs.
//
// TODO: add a driver API to wait for context manager, or
// stop special casing handle 0 for context manager and add
// a driver API to get a handle to the context manager with
// proper reference counting.
Parcel data;
status_t status = IPCThreadState::self()->transact(
0, IBinder::PING_TRANSACTION, data, NULL, 0);
if (status == DEAD_OBJECT)
return NULL;
}
b = new BpBinder(handle); //传进来的handle等于0
e->binder = b;
if (b) e->refs = b->getWeakRefs();
result = b;
} 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;
}
BpBinder::BpBinder(int32_t handle)
: mHandle(handle)//handle赋值给mHandle=0
, mAlive(1)
, mObitsSent(0)
, mObituaries(NULL)
{
ALOGV("Creating BpBinder %p handle %d\n", this, mHandle);
extendObjectLifetime(OBJECT_LIFETIME_WEAK);
IPCThreadState::self()->incWeakHandle(handle);
}
interface_cast(ProcessState::self()->getContextObject(NULL));获得BpServiceManager对象,new BpServiceManager(new BpBinder(0))
interface_cast模板方法调用IServiceManager的asInterface方法,并把new BpBinder(0)传给asInterface方法。
- IServiceManager的asInterface方法在IServiceManager类中通过DECLARE_META_INTERFACE(ServiceManager);进行声明
- IServiceManager的asInterface方法在BpServiceManager类中通过IMPLEMENT_META_INTERFACE(ServiceManager, “android.os.IServiceManager”);进行实现
//源码:https://github.com/CyanogenMod/android_frameworks_native/blob/cm-14.1/include/binder/IInterface.h#L42
template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
return INTERFACE::asInterface(obj);
}
class IServiceManager : public IInterface
{
public:
//声明接口
DECLARE_META_INTERFACE(ServiceManager);
/**
* Retrieve an existing service, blocking for a few seconds
* if it doesn't yet exist.
*/
virtual sp<IBinder> getService( const String16& name) const = 0;
/**
* Retrieve an existing service, non-blocking.
*/
virtual sp<IBinder> checkService( const String16& name) const = 0;
/**
* Register a service.
*/
virtual status_t addService( const String16& name,
const sp<IBinder>& service,
bool allowIsolated = false) = 0;
/**
* Return list of all existing services.
*/
virtual Vector<String16> listServices() = 0;
enum {
GET_SERVICE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
CHECK_SERVICE_TRANSACTION,
ADD_SERVICE_TRANSACTION,
LIST_SERVICES_TRANSACTION,
};
};
class BpServiceManager : public BpInterface<IServiceManager>
{
public:
BpServiceManager(const sp<IBinder>& impl)
: BpInterface<IServiceManager>(impl)
{
}
virtual sp<IBinder> getService(const String16& name) const
{
unsigned n;
for (n = 0; n < 5; n++){
sp<IBinder> svc = checkService(name);
if (svc != NULL) return svc;
ALOGI("Waiting for service %s...\n", String8(name).string());
sleep(1);
}
return NULL;
}
virtual sp<IBinder> checkService( const String16& name) const
{
Parcel data, reply;
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeString16(name);
remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply);
return reply.readStrongBinder();
}
virtual status_t addService(const String16& name, const sp<IBinder>& service,
bool allowIsolated)
{
Parcel data, reply;
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeString16(name);
data.writeStrongBinder(service);
data.writeInt32(allowIsolated ? 1 : 0);
status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
return err == NO_ERROR ? reply.readExceptionCode() : err;
}
virtual Vector<String16> listServices()
{
Vector<String16> res;
int n = 0;
for (;;) {
Parcel data, reply;
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeInt32(n++);
status_t err = remote()->transact(LIST_SERVICES_TRANSACTION, data, &reply);
if (err != NO_ERROR)
break;
res.add(reply.readString16());
}
return res;
}
};
//实现接口
IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");
}; // namespace android
//通过预处理器运算符##(标记粘合符),声明接口
#define DECLARE_META_INTERFACE(INTERFACE) \
static const android::String16 descriptor; \
static android::sp<I##INTERFACE> asInterface( \
const android::sp<android::IBinder>& obj); \
virtual const android::String16& getInterfaceDescriptor() const; \
I##INTERFACE(); \
virtual ~I##INTERFACE();
//通过预处理器运算符##(标记粘合符),实现接口
#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME) \
const android::String16 I##INTERFACE::descriptor(NAME); \
const android::String16& \
I##INTERFACE::getInterfaceDescriptor() const { \
return I##INTERFACE::descriptor; \
} \
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) { \
intr = new Bp##INTERFACE(obj); \
} \
} \
return intr; \
} \
I##INTERFACE::I##INTERFACE() { } \
I##INTERFACE::~I##INTERFACE() { }
##INTERFACE用ServiceManager替换,得到BpServiceManager对象
BpBinder在BpServiceManager中如何存储?
new BpServiceManager(new BpBinder(0)),最终将BpBinder对象存储到了BpRefBase对象的mRemote成员中
//BpBinder对象传给了impl
BpServiceManager(const sp<IBinder>& impl)
: BpInterface<IServiceManager>(impl)
{
}
//impl传给了remote
template<typename INTERFACE>
inline BpInterface<INTERFACE>::BpInterface(const sp<IBinder>& remote)
: BpRefBase(remote)
{
}
//remote传给了mRemote
BpRefBase::BpRefBase(const sp<IBinder>& o)
: mRemote(o.get()), mRefs(NULL), mState(0)
{
extendObjectLifetime(OBJECT_LIFETIME_WEAK);
if (mRemote) {
mRemote->incStrong(this); // Removed on first IncStrong().
mRefs = mRemote->createWeak(this); // Held for our entire lifetime.
}
}
总结
defaultServiceManager方法构造了一个BpServiceManager对象,它里面的mRemote = new BpBinder(0),也就是mRmote->mHandle=0
1.2 分析如何获得BpHelloServie对象
BpHelloServie继承关系图,和上面讲到的BpServiceManager的继承关系类似。唯一不同的是BpServiceManager的handle是固定的0(代表servicemanager服务进程),而BpHelloServie的handle要通过BpServiceManager的getService方法获得。
BpHelloService是HelloService服务的代理,通过BpHelloServie可以调用HelloServie服务中提供的服务函数(sayhello/sayhello_to),BpHelloService对象的获取过程有两步:
- 通过BpServiceManager的getService方法获取指向hello服务的BpBinder对象。
- 将BpBinder对象转换为BpServiceManager对象。
下面通过源码进行验证
int main(int argc, char **argv)
{
int cnt;
if (argc < 2){
ALOGI("Usage:\n");
ALOGI("%s <readfile>\n", argv[0]);
ALOGI("%s <hello|goodbye>\n", argv[0]);
ALOGI("%s <hello|goodbye> <name>\n", argv[0]);
return -1;
}
/* getService */
/* 打开驱动, mmap */
sp<ProcessState> proc(ProcessState::self());
/* 获得BpServiceManager */
sp<IServiceManager> sm = defaultServiceManager();
if (strcmp(argv[1], "hello") == 0)
{
// 从servicemanager获得hello服务的BpBinder对象
sp<IBinder> binder =
sm->getService(String16("hello"));
if (binder == 0)
{
ALOGI("can't get hello service\n");
return -1;
}
/* 将binder转换为BpHelloService对象,这里的service肯定是BpHelloServie指针 */
sp<IHelloService> service =
interface_cast<IHelloService>(binder);
/* 调用Service的函数 */
if (argc < 3) {
service->sayhello();
ALOGI("client call sayhello");
}
else {
cnt = service->sayhello_to(argv[2]);
ALOGI("client call sayhello_to, cnt = %d", cnt);
}
}
return 0;
}
sp binder = sm->getService(String16(“hello”))源码分析,这里binder是BpBinder对象,里面含有HelloService的handle
virtual sp<IBinder> getService(const String16& name) const
{
unsigned n;
for (n = 0; n < 5; n++){
// 从servicemanager获取服务
sp<IBinder> svc = checkService(name);
if (svc != NULL) return svc;
ALOGI("Waiting for service %s...\n", String8(name).string());
sleep(1);
}
return NULL;
}
virtual sp<IBinder> checkService( const String16& name) const
{
Parcel data, reply;
//构造数据
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeString16(name);//name = "hello"
//发送数据:给handle=0,即service_manager进程
remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply);
//从收到的回复中取出HelloService的handle,构造BpBinder
return reply.readStrongBinder();
}
sp<IBinder> Parcel::readStrongBinder() const
{
sp<IBinder> val;
readStrongBinder(&val);
return val;
}
status_t Parcel::readStrongBinder(sp<IBinder>* val) const
{
return unflatten_binder(ProcessState::self(), *this, val);
}
status_t unflatten_binder(const sp<ProcessState>& proc,
const Parcel& in, sp<IBinder>* out)
{
const flat_binder_object* flat = in.readObject(false);
if (flat) {
switch (flat->type) {
case BINDER_TYPE_BINDER:
*out = reinterpret_cast<IBinder*>(flat->cookie);
return finish_unflatten_binder(NULL, *flat, in);
case BINDER_TYPE_HANDLE:
// flat->handle是hello服务handle,客户端可以通过这个handle找到hello服务
*out = proc->getStrongProxyForHandle(flat->handle);
return finish_unflatten_binder(
static_cast<BpBinder*>(out->get()), *flat, in);
}
}
return BAD_TYPE;
}
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
sp<IBinder> result;
AutoMutex _l(mLock);
handle_entry* e = lookupHandleLocked(handle);
if (e != NULL) {
// We need to create a new BpBinder if there isn't currently one, OR we
// are unable to acquire a weak reference on this current one. See comment
// in getWeakProxyForHandle() for more info about this.
IBinder* b = e->binder;
if (b == NULL || !e->refs->attemptIncWeak(this)) {
if (handle == 0) {
// Special case for context manager...
// The context manager is the only object for which we create
// a BpBinder proxy without already holding a reference.
// Perform a dummy transaction to ensure the context manager
// is registered before we create the first local reference
// to it (which will occur when creating the BpBinder).
// If a local reference is created for the BpBinder when the
// context manager is not present, the driver will fail to
// provide a reference to the context manager, but the
// driver API does not return status.
//
// Note that this is not race-free if the context manager
// dies while this code runs.
//
// TODO: add a driver API to wait for context manager, or
// stop special casing handle 0 for context manager and add
// a driver API to get a handle to the context manager with
// proper reference counting.
Parcel data;
status_t status = IPCThreadState::self()->transact(
0, IBinder::PING_TRANSACTION, data, NULL, 0);
if (status == DEAD_OBJECT)
return NULL;
}
//构造BpBinder,handle是ServiceManager的handle
b = new BpBinder(handle);
e->binder = b;
if (b) e->refs = b->getWeakRefs();
result = b;
} 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;
}
sp service = interface_cast(binder),使用BpBinder(其中的handle是HelloService的handle)获得一个IHelloService的接口(其实是BpHelloService对象),这个过程和上面将BpBinder对象转换为BpServiceManager对象的过程一致,不再赘述。
1.3 代理类如何发送数据?
代理类通过如下两个步骤发送数据
- 构造数据
- 调用remote()->transact
如BpServiceManager发送数据源码
class BpServiceManager : public BpInterface<IServiceManager>
{
public:
BpServiceManager(const sp<IBinder>& impl)
: BpInterface<IServiceManager>(impl)
{
}
virtual sp<IBinder> getService(const String16& name) const
{
unsigned n;
for (n = 0; n < 5; n++){
sp<IBinder> svc = checkService(name);
if (svc != NULL) return svc;
ALOGI("Waiting for service %s...\n", String8(name).string());
sleep(1);
}
return NULL;
}
virtual sp<IBinder> checkService( const String16& name) const
{
Parcel data, reply;
// 构造数据
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeString16(name);
// 调用remote()->transact
remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply);
return reply.readStrongBinder();
}
virtual status_t addService(const String16& name, const sp<IBinder>& service,
bool allowIsolated)
{
Parcel data, reply;
// 构造数据
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeString16(name);
data.writeStrongBinder(service);
data.writeInt32(allowIsolated ? 1 : 0);
// 调用remote()->transact
status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
return err == NO_ERROR ? reply.readExceptionCode() : err;
}
......
};
如BpHelloService发送数据源码
class BpHelloService: public BpInterface<IHelloService>
{
public:
BpHelloService(const sp<IBinder>& impl)
: BpInterface<IHelloService>(impl)
{
}
void sayhello(void)
{
/* 构造/发送数据 */
Parcel data, reply;
data.writeInt32(0);
data.writeString16(String16("IHelloService"));
// 调用remote()->transact
remote()->transact(HELLO_SVR_CMD_SAYHELLO, data, &reply);
}
int sayhello_to(const char *name)
{
/* 构造/发送数据 */
Parcel data, reply;
int exception;
data.writeInt32(0);
data.writeString16(String16("IHelloService"));
data.writeString16(String16(name));
// 调用remote()->transact
remote()->transact(HELLO_SVR_CMD_SAYHELLO_TO, data, &reply);
exception = reply.readInt32();
if (exception)
return -1;
else
return reply.readInt32();
}
......
};
我们来分析下remote()->transact
- remote()函数获得是BpRefBase中的mRemote,而mRemote指向的是BpBinder,这点从上面分析获得BpServiceManager和BpHelloService对象的时候可知。
class BpRefBase : public virtual RefBase
{
protected:
BpRefBase(const sp<IBinder>& o);
virtual ~BpRefBase();
virtual void onFirstRef();
virtual void onLastStrongRef(const void* id);
virtual bool onIncStrongAttempted(uint32_t flags, const void* id);
inline IBinder* remote() { return mRemote; }
inline IBinder* remote() const { return mRemote; }
private:
BpRefBase(const BpRefBase& o);
BpRefBase& operator=(const BpRefBase& o);
IBinder* const mRemote; // BpBinder对象
RefBase::weakref_type* mRefs;
std::atomic<int32_t> mState;
};
- 那么接着分析BpBinder中的transact函数
transact调用IPCThreadState::self()->transact方法,接着调用waitForResponse方法,接着调用talkWithDriver方法,而talkWithDriver方法最终调用ioctl发送数据。
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) {
//这儿的参数就和C的ioctl需要的参数差不多了,mHandle是指目的进程,code是指调用服务的哪个函数
//data是携带的数据,reply是要回复的数据
status_t status = IPCThreadState::self()->transact(
mHandle, code, data, reply, flags);
if (status == DEAD_OBJECT) mAlive = 0;
return status;
}
return DEAD_OBJECT;
}
status_t IPCThreadState::transact(int32_t handle,
uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags)
{
status_t err = data.errorCheck();
flags |= TF_ACCEPT_FDS;
IF_LOG_TRANSACTIONS() {
TextOutput::Bundle _b(alog);
alog << "BC_TRANSACTION thr " << (void*)pthread_self() << " / hand "
<< handle << " / code " << TypeCode(code) << ": "
<< indent << data << dedent << endl;
}
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);
}
if (err != NO_ERROR) {
if (reply) reply->setError(err);
return (mLastError = err);
}
if ((flags & TF_ONE_WAY) == 0) {
#if 0
if (code == 4) { // relayout
ALOGI(">>>>>> CALLING transaction 4");
} else {
ALOGI(">>>>>> CALLING transaction %d", code);
}
#endif
if (reply) {
err = waitForResponse(reply);
} else {
Parcel fakeReply;
err = waitForResponse(&fakeReply);
}
#if 0
if (code == 4) { // relayout
ALOGI("<<<<<< RETURNING transaction 4");
} else {
ALOGI("<<<<<< RETURNING transaction %d", code);
}
#endif
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);
}
return err;
}
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{
uint32_t cmd;
int32_t err;
while (1) {
if ((err=talkWithDriver()) < NO_ERROR) break;
err = mIn.errorCheck();
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;
}
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) {
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:
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;
}
return err;
}
status_t IPCThreadState::talkWithDriver(bool doReceive)
{
if (mProcess->mDriverFD <= 0) {
return -EBADF;
}
binder_write_read bwr;
// 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();
// This is what we'll read.
if (doReceive && needRead) {
bwr.read_size = mIn.dataCapacity();
bwr.read_buffer = (uintptr_t)mIn.data();
} else {
bwr.read_size = 0;
bwr.read_buffer = 0;
}
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;
do {
IF_LOG_COMMANDS() {
alog << "About to read/write, write size = " << mOut.dataSize() << endl;
}
#if defined(__ANDROID__)
// 最终还是要调用ioctl发送数据
if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
err = NO_ERROR;
else
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;
}
2. test_server.cpp源码解析
启动一个binder服务有以下几个步骤:
- 打开驱动
- 注册服务
- 死循环等待数据
其中,打开驱动是通过ProcessState对象完成的,循环等待数据是由IPCThreadState创建的主线程和ProcessState创建的子线程完成的。
2.1 分析数据传输机制ProcessState和IPCThreadState
ProcessState对象打开驱动
/* usage : test_server */
int main(void)
{
/* 打开驱动, mmap */
sp<ProcessState> proc(ProcessState::self());
/* 获得BpServiceManager */
sp<IServiceManager> sm = defaultServiceManager();
sm->addService(String16("hello"), new BnHelloService(sockets[1]));
sm->addService(String16("goodbye"), new BnGoodbyeService());
/* 创建循环体,等待被被唤醒:读取数据,解析数据,处理数据,回复数据 */
ProcessState::self()->startThreadPool();//创建子线程的IPCThreadState
IPCThreadState::self()->joinThreadPool();//创建主线程的IPCThreadState,并循环等待数据
return 0;
}
ProcessState::self()打开驱动
sp<ProcessState> ProcessState::self()
{
Mutex::Autolock _l(gProcessMutex);
if (gProcess != NULL) {
return gProcess;
}
gProcess = new ProcessState;
return gProcess;
}
ProcessState::ProcessState()
: mDriverFD(open_driver())//打开驱动,并将fd赋值给mDriverFD
, mVMStart(MAP_FAILED)
, 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)
, mThreadPoolSeq(1)
{
if (mDriverFD >= 0) {
// mmap,提供一块虚拟地址空间来接收事务
// mmap the binder, providing a chunk of virtual address space to receive transactions.
mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
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.");
}
static int open_driver()
{
int fd = open("/dev/binder", O_RDWR | O_CLOEXEC);
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) {
ALOGE("Binder driver protocol does not match user space protocol!");
close(fd);
fd = -1;
}
size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;
result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
if (result == -1) {
ALOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
}
} else {
ALOGW("Opening '/dev/binder' failed: %s\n", strerror(errno));
}
return fd;
}
IPCThreadState::self()->joinThreadPool();创建主线程IPCThreadState对象,并循环等待客户端数据
补充知识点:线程特有数据(Thread Special Data)
主线程创建多个子线程,每个子线程有自己的IPCThreadState对象,即该对象是线程特有的,各自不同,那么它应该存在线程的局部空间里。
那么如何实现呢?
- 创建键:k = pthread_key_create
(k,v)- 为键设置值:每个线程为k设置不一样的value
如对于线程1可以调用pthread_setspecific(k, v1),设置value为v1,- 后续可以在不同线程中获得不同的值
如在线程1中调用pthread_getspecific(k)就可以得到v1
// 保证每个线程只有一个IPCThreadState对象,该对象通过pthread_getspecific函数获得
IPCThreadState* IPCThreadState::self()
{
if (gHaveTLS) {
restart:
const pthread_key_t k = gTLS;
//获得值
IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);
if (st) return st;
//创建IPCThreadState对象,作为已经创建的键的值
return new IPCThreadState;
}
if (gShutdown) {
ALOGW("Calling IPCThreadState::self() during shutdown is dangerous, expect a crash.\n");
return NULL;
}
//多线程下也只会创建一个键
pthread_mutex_lock(&gTLSMutex);
if (!gHaveTLS) {
//创建键
int key_create_value = pthread_key_create(&gTLS, threadDestructor);
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;
}
IPCThreadState::IPCThreadState()
//mProcess = ProcessState::self(),里面含有open驱动的句柄 mDriverFD
: mProcess(ProcessState::self()),
mMyThreadId(gettid()),
mStrictModePolicy(0),
mLastTransactionBinderFlags(0)
{
//将IPCThreadState对象设置为已经创建的键的值
pthread_setspecific(gTLS, this);
clearCaller();
mIn.setDataCapacity(256);
mOut.setDataCapacity(256);
}
IPCThreadState::self()保证每个线程只有一个IPCThreadState对象,该对象通过pthread_getspecific函数获得。IPCThreadState::self()->joinThreadPool()方法循环等待 读取,解析,处理,返回数据
// 循环等待 读取,解析,处理,返回数据
void IPCThreadState::joinThreadPool(bool isMain)
{
LOG_THREADPOOL("**** THREAD %p (PID %d) IS JOINING THE THREAD POOL\n", (void*)pthread_self(), getpid());
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);
status_t result;
//循环等待数据
do {
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);
}
status_t IPCThreadState::getAndExecuteCommand()
{
status_t result;
int32_t cmd;
//调用ioctl获取数据
result = talkWithDriver();
if (result >= NO_ERROR) {
size_t IN = mIn.dataAvail();
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->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);
// After executing the command, ensure that the thread is returned to the
// foreground cgroup before rejoining the pool. The driver takes care of
// restoring the priority, but doesn't do anything with cgroups so we
// need to take care of that here in userspace. Note that we do make
// sure to go in the foreground after executing a transaction, but
// there are other callbacks into user code that could have changed
// our group so we want to make absolutely sure it is put back.
set_sched_policy(mMyThreadId, SP_FOREGROUND);
}
return result;
}
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_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;
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) {
// We have inherited a reduced priority from the caller, but do not
// want to run in that state in this process. The driver set our
// priority already (though not our scheduling class), so bounce
// it back to the default before invoking the transaction.
setpriority(PRIO_PROCESS, mMyThreadId, ANDROID_PRIORITY_NORMAL);
}
} else {
if (curPrio >= ANDROID_PRIORITY_BACKGROUND) {
// We want to use the inherited priority from the caller.
// Ensure this thread is in the background scheduling class,
// since the driver won't modify scheduling classes for us.
// The scheduling group is reset to default by the caller
// once this method returns after the transaction is complete.
set_sched_policy(mMyThreadId, SP_BACKGROUND);
}
}
//ALOGI(">>>> TRANSACT from pid %d uid %d\n", mCallingPid, mCallingUid);
Parcel reply;
status_t error;
IF_LOG_TRANSACTIONS() {
TextOutput::Bundle _b(alog);
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) {
// We only have a weak reference on the target object, so we must first try to
// safely acquire a strong reference before doing anything else with it.
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 {
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;
......
}
if (result != NO_ERROR) {
mLastError = result;
}
return result;
}
ProcessState::self()->startThreadPool(),创建子线程的IPCThreadState,并循序等待数据
void ProcessState::startThreadPool()
{
AutoMutex _l(mLock);
if (!mThreadPoolStarted) {
mThreadPoolStarted = true;
spawnPooledThread(true);
}
}
void ProcessState::spawnPooledThread(bool isMain)
{
if (mThreadPoolStarted) {
String8 name = makeBinderThreadName();
ALOGV("Spawning new pooled thread, name=%s\n", name.string());
//创建子线程
sp<Thread> t = new PoolThread(isMain);
t->run(name.string());
}
}
class PoolThread : public Thread
{
public:
PoolThread(bool isMain)
: mIsMain(isMain)
{
}
protected:
virtual bool threadLoop()
{
//为子线程创建IPCThreadState,并进行循环等待数据
IPCThreadState::self()->joinThreadPool(mIsMain);
return false;
}
const bool mIsMain;
};
2.2 分析向servicemanager添加服务的具体过程
对于不同的服务,构造flat_binder_object结构体,里面的binder/cookie对于不同的服务它的值不一样
/* 获得BpServiceManager */
sp<IServiceManager> sm = defaultServiceManager();
sm->addService(String16("hello"), new BnHelloService());
virtual status_t addService(const String16& name, const sp<IBinder>& service,
bool allowIsolated)
{
Parcel data, reply;
// 构造数据
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeString16(name);
data.writeStrongBinder(service);// service = BnHelloService对象
data.writeInt32(allowIsolated ? 1 : 0);
// 发送数据
status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
return err == NO_ERROR ? reply.readExceptionCode() : err;
}
status_t writeStrongBinder(const sp<T>& val) {
return writeStrongBinder(T::asBinder(val)); // val = BnHelloService对象
}
status_t Parcel::writeStrongBinder(const sp<IBinder>& val)
{
return flatten_binder(ProcessState::self(), val, this);// val = BnHelloService对象
}
status_t flatten_binder(const sp<ProcessState>& /*proc*/,
const sp<IBinder>& binder, Parcel* out)// binder = BnHelloService对象
{
//构造flat_binder_object
flat_binder_object obj;
obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
if (binder != NULL) {
IBinder *local = binder->localBinder();//local 指向 BnHelloService对象
if (!local) {
BpBinder *proxy = binder->remoteBinder();
if (proxy == NULL) {
ALOGE("null proxy");
}
const int32_t handle = proxy ? proxy->handle() : 0;
obj.type = BINDER_TYPE_HANDLE;
obj.binder = 0; /* Don't pass uninitialized stack data to a remote process */
obj.handle = handle;
obj.cookie = 0;
} else {
obj.type = BINDER_TYPE_BINDER;
obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs());
obj.cookie = reinterpret_cast<uintptr_t>(local); // 指向 BnHelloService对象
}
} else {
obj.type = BINDER_TYPE_BINDER;
obj.binder = 0;
obj.cookie = 0;
}
return finish_flatten_binder(binder, obj, out);
}
BBinder* BBinder::localBinder()
{
return this;
}
2.3 分析server如何分辨client想使用哪一个服务,并调用对应的函数
server收到的数据里含有flat_binder_object结构体,它可以根据binder/cookie分析client想使用哪一个服务,把cookie转为BnXXX对象,然后调用它的函数
void IPCThreadState::joinThreadPool(bool isMain)
{
LOG_THREADPOOL("**** THREAD %p (PID %d) IS JOINING THE THREAD POOL\n", (void*)pthread_self(), getpid());
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);
status_t result;
do {
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);
}
status_t IPCThreadState::getAndExecuteCommand()
{
status_t result;
int32_t cmd;
//调用ioctl获取数据
result = talkWithDriver();
if (result >= NO_ERROR) {
size_t IN = mIn.dataAvail();
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->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);
// After executing the command, ensure that the thread is returned to the
// foreground cgroup before rejoining the pool. The driver takes care of
// restoring the priority, but doesn't do anything with cgroups so we
// need to take care of that here in userspace. Note that we do make
// sure to go in the foreground after executing a transaction, but
// there are other callbacks into user code that could have changed
// our group so we want to make absolutely sure it is put back.
set_sched_policy(mMyThreadId, SP_FOREGROUND);
}
return result;
}
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_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;
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) {
// We have inherited a reduced priority from the caller, but do not
// want to run in that state in this process. The driver set our
// priority already (though not our scheduling class), so bounce
// it back to the default before invoking the transaction.
setpriority(PRIO_PROCESS, mMyThreadId, ANDROID_PRIORITY_NORMAL);
}
} else {
if (curPrio >= ANDROID_PRIORITY_BACKGROUND) {
// We want to use the inherited priority from the caller.
// Ensure this thread is in the background scheduling class,
// since the driver won't modify scheduling classes for us.
// The scheduling group is reset to default by the caller
// once this method returns after the transaction is complete.
set_sched_policy(mMyThreadId, SP_BACKGROUND);
}
}
//ALOGI(">>>> TRANSACT from pid %d uid %d\n", mCallingPid, mCallingUid);
Parcel reply;
status_t error;
IF_LOG_TRANSACTIONS() {
TextOutput::Bundle _b(alog);
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) {
// We only have a weak reference on the target object, so we must first try to
// safely acquire a strong reference before doing anything else with it.
if (reinterpret_cast<RefBase::weakref_type*>(
tr.target.ptr)->attemptIncStrong(this)) {
//reinterpret_cast<BBinder*>(tr.cookie) 通过cookie构造指向BnHelloService对象的BBinder
//然后调用BBinder的transact函数
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 {
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;
......
}
if (result != NO_ERROR) {
mLastError = result;
}
return result;
}
status_t BBinder::transact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
data.setDataPosition(0);
status_t err = NO_ERROR;
switch (code) {
case PING_TRANSACTION:
reply->writeInt32(pingBinder());
break;
default:
//调用BnHelloService实现的onTransact方法
err = onTransact(code, data, reply, flags);
break;
}
if (reply != NULL) {
reply->setDataPosition(0);
}
return err;
}
status_t BnHelloService::onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags)
{
/* 解析数据,调用sayhello/sayhello_to */
switch (code) {
case HELLO_SVR_CMD_SAYHELLO: {
sayhello();
reply->writeInt32(0); /* no exception */
return NO_ERROR;
} break;
case HELLO_SVR_CMD_SAYHELLO_TO: {
/* 从data中取出参数 */
int32_t policy = data.readInt32();
String16 name16_tmp = data.readString16(); /* IHelloService */
String16 name16 = data.readString16();
String8 name8(name16);
int cnt = sayhello_to(name8.string());
/* 把返回值写入reply传回去 */
reply->writeInt32(0); /* no exception */
reply->writeInt32(cnt);
return NO_ERROR;
} break;
case HELLO_SVR_CMD_GET_FD: {
int fd = this->get_fd();
reply->writeInt32(0); /* no exception */
/* 参考:
* frameworks\base\core\jni\android_view_InputChannel.cpp
* android_view_InputChannel_nativeWriteToParcel
*/
reply->writeDupFileDescriptor(fd);
return NO_ERROR;
} break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
}