一、简介
Binder是Android系统中的一种进程间通信机制,但是Binder相对于其他IPC机制,更加灵活和方便。而应用中最多的就是AIDL机制。整片也是为自己的Binder理解加深影响。
Linux环境
在Linux系统中,系统会给每个进程分配虚拟内存,然后系统会将这个虚拟内存空间映射到物理内存空间,只有操作系统才能操作物理空间。由于进程只能操作虚拟内存,无法操作其他进程内存空间,因此需要一个跨进程通信机制。
起源
在我们需要调用物理内存时,需要从一个进程跨越另一个进程,就需要操作系统来支持,而Linux的动态加载内核模块机制可以完成,模块是具有独立功能的程序。在Android系统中添加这个内核模块,就可以让他来完成两个进程中间的传输媒介,即Binder驱动。
优势(管道、消息队列、共享内存、套接字)
- 传输性能:复杂数据类型传递可以复用内存,需要拷贝1次数据
- 安全性:支持通信身份校验,提高安全性。
模型
github
可以看到这里都会想ServerManager传输消息
Server端通过Binder驱动在ServiceManager中注册
Client端通过Binder驱动获取ServiceManager中注册的Server端
Client端通过Binder驱动和Server端进行通讯
涉及相关类
下图为Binder机制中使用到的Java类和Native层类:
github
Binder和BinderProxy都实现了IBinder接口
ActivityManagerService继承自ActivityManagerNative
Native层的的重要文件中有android_util_Binder.cpp和android_os_Parcel.cpp
ServiceManager为重要的类,Server进程要先注册到这里。
二、源码跟踪
下面一步步跟进源码,版本或有不同,可能会找不到相关类。
android_util_Binder.cpp Binder初始化
在Java调用前期,系统会提前注册JNI函数,他们专门负责连接Java层和Native层的交互。
frameworks/base/core/jni/android_util_Binder.cpp:/**
* 负责专门搭建JavaBinder和NativeBinder交互的函数
*/
int register_android_os_Binder(JNIEnv* env)
{
// 初始化Java Binder类和Native层的关系
if (int_register_android_os_Binder(env) < 0)
return -1;
// 初始化Java BinderInternal类和Native层的关系
if (int_register_android_os_BinderInternal(env) < 0)
return -1;
// 初始化Java Proxy类和Native层的关系
if (int_register_android_os_BinderProxy(env) < 0)
return -1;
......
return 0;
}
这里是主注册点,可以看到里面的三个函数分别调用其他的注册功能。
Binder类初始化
frameworks/base/core/jni/android_util_Binder.cpp:/**
* Binder类初始化
*/
static int int_register_android_os_Binder(JNIEnv* env)
{
// android/os/Binder
jclass clazz = FindClassOrDie(env, kBinderPathName);
// gBinderOffsets是一个静态类对象,专门保护Binder类的一些JNI层中使用的信息
gBinderOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
gBinderOffsets.mExecTransact = GetMethodIDOrDie(env, clazz, "execTransact", "(IJJI)Z");
gBinderOffsets.mObject = GetFieldIDOrDie(env, clazz, "mObject", "J");
// 注册Binder类中native函数的实现
return RegisterMethodsOrDie(
env, kBinderPathName,
gBinderMethods, NELEM(gBinderMethods));
}
最后保存到gBinderOffsets
参数。
BinderInternal类初始化
frameworks/base/core/jni/android_util_Binder.cpp:/**
* BinderInternal类初始化
*/
static int int_register_android_os_BinderInternal(JNIEnv* env)
{
// 根据全路径名找到jclass对象
// com/android/internal/os/BinderInternal
jclass clazz = FindClassOrDie(env, kBinderInternalPathName);
// gBinderInternalOffsets也是一个静态对象,用来保存BinderInternal类的一些信息
gBinderInternalOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
// 获取forceBinderGc的methodID
gBinderInternalOffsets.mForceGc = GetStaticMethodIDOrDie(env, clazz, "forceBinderGc", "()V");
// 注册BinderInternal类中native函数的实现
return RegisterMethodsOrDie(
env, kBinderInternalPathName,
gBinderInternalMethods, NELEM(gBinderInternalMethods));
}
最后保存到gBinderInternalOffsets
参数。
BinderProxy类初始化
frameworks/base/core/jni/android_util_Binder.cpp:/**
* BinderProxy类初始化
*/
static int int_register_android_os_BinderProxy(JNIEnv* env)
{
// Error
jclass clazz = FindClassOrDie(env, "java/lang/Error");
// gErrorOffsets用来和Error类交互
gErrorOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
// gBinderProxyOffsets用来和BinderProxy类交互
clazz = FindClassOrDie(env, kBinderProxyPathName);
gBinderProxyOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
gBinderProxyOffsets.mConstructor = GetMethodIDOrDie(env, clazz, "<init>", "()V");
gBinderProxyOffsets.mSendDeathNotice = GetStaticMethodIDOrDie(env, clazz, "sendDeathNotice",
"(Landroid/os/IBinder$DeathRecipient;)V");
gBinderProxyOffsets.mObject = GetFieldIDOrDie(env, clazz, "mObject", "J");
// 获取WeakRefere
gBinderProxyOffsets.mSelf = GetFieldIDOrDie(env, clazz, "mSelf",
"Ljava/lang/ref/WeakReference;");
gBinderProxyOffsets.mOrgue = GetFieldIDOrDie(env, clazz, "mOrgue", "J");
// gClassOffsets用来和Class类交互
clazz = FindClassOrDie(env, "java/lang/Class");
gClassOffsets.mGetName = GetMethodIDOrDie(env, clazz, "getName", "()Ljava/lang/String;");
// 注册BinderProxy
return RegisterMethodsOrDie(
env, kBinderProxyPathName,
gBinderProxyMethods, NELEM(gBinderProxyMethods));
}
最后保存到gBinderProxyOffsets
参数。
可以看到这里的三个功能分别对应了三个参数:gBinderOffsets、gBinderInternalOffsets、gBinderProxyOffsets。
准备好这些后,就开始进入Java源码
入口ActivityManagerService
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java: public void setSystemProcess() {
try {
// 将ActivityManagerService服务注册到ServiceManager中
ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);
......
}
这里就是我们Activity开始的地方,也是Binder的入口点。
可以看到,调用的是ServiceManager的addService方法将自己传递进去,而Context.ACTIVITY_SERVICE
就是activity
字符串。
frameworks/base/tools/layoutlib/bridge/src/android/os/ServiceManager.java:public static void addService(String name, IBinder service, boolean allowIsolated) {
try {
getIServiceManager().addService(name, service, allowIsolated);
} catch (RemoteException e) {
Log.e(TAG, "error in addService", e);
}
}
private static IServiceManager getIServiceManager() {
if (sServiceManager != null) {
return sServiceManager;
}
sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
return sServiceManager;
}
这里有调用addService函数的是getIServiceManager()
。而这个函数中调用的是ServiceManagerNative的asInterface()
函数。另外一个就是BinderInternal.getContextObject()
参数。
BinderInternal.getContextObject()
该函数调用至Native层
frameworks/base/core/jni/android_util_Binder.cpp:// ServiceManager 中调用至此,
static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
return javaObjectForIBinder(env, b);
}
这里调用ProcessState的getContextObject()函数。这里传递NULL,即0。
ProcessState 传递给Binder驱动的线程管理
frameworks/native/libs/binder/ProcessState.cpp: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) {
IBinder* b = e->binder;
if (b == NULL || !e->refs->attemptIncWeak(this)) {
// 对于新创建的资源项,他的Binder为空时
if (handle == 0) {
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);
// 填充entry的内容
e->binder = b;
if (b) e->refs = b->getWeakRefs();
result = b;
} else {
result.force_set(b);
e->refs->decWeak(this);
}
}
return result;
}
进入ProcessState.h文件中可以看到,ProcessState继承自RefBase。
在这里看到new了一个BpBinder对象
,并returb出去。那么BpBinder是什么:
BpBinder和BBinder
他们都继承自Binder类,他们是一一对应的。
BpBinder是客户端用来与Server交互的代理类,也即BinderProxy
BBinder则是和proxy相对的一端,他是proxy交互的目的端。也即服务端
这里传入的handler
则是用来标识他们是值,这里传0就代表的就是ServiceManager所对应的BpBinder。
我们看一下BpBinder的源码
frameworks/native/libs/binder/BpBinder.cpp:BpBinder::BpBinder(int32_t handle)
: mHandle(handle)
, mAlive(1)
, mObitsSent(0)
, mObituaries(NULL)
{
extendObjectLifetime(OBJECT_LIFETIME_WEAK);
IPCThreadState::self()->incWeakHandle(handle);
}
这里初始化BpBinder,重要地方是IPCThreadState
对象。
javaObjectForIBinder() 绑定bpBinder和BinderProxy
最后就是调用了下面这个函数:
frameworks/base/core/jni/android_util_Binder.cpp:jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val./////i)
{
jobject object = (jobject)val->findObject(&gBinderProxyOffsets);
if (object != NULL) {
jobject res = jniGetReferent(env, object);
if (res != NULL) {
return res;
}
android_atomic_dec(&gNumProxyRefs);
val->detachObject(&gBinderProxyOffsets);
env->DeleteGlobalRef(object);
}
object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);
if (object != NULL) {
env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get());
val->incStrong((void*)javaObjectForIBinder);
jobject refObject = env->NewGlobalRef(
env->GetObjectField(object, gBinderProxyOffsets.mSelf));
val->attachObject(&gBinderProxyOffsets, refObject,
jnienv_to_javavm(env), proxy_cleanup);
}
return object;
}
这里代码很多:
- 首先调用调用BpBinder的
findObject()
函数,在BpBinder中有一个ObjectManager来管理创建的Java BpBinder对象KeyedVector<const void*, entry_t> mObjects;
。这里回去寻找gBinderProxyOffsets是否保存在ObjectManager中。如果有,则删除。 - 根据gBinderProxyOffsets创建一个新的object,也即BinderProxy对象,并注册到BpBinder的ObjectManager中。
这里使BpBinder与BinderProxy产生关联。
好,这里结束后就知道返回去的是一个BpBinder参数给asInterface()函数
ServiceManagerNative.asInterface()
继续让我们看看ServiceManagerNative
类的大致和asInterface()
函数
frameworks/base/core/java/android/os/ServiceManagerNative.java:public abstract class ServiceManagerNative extends Binder implements IServiceManager{
static public IServiceManager asInterface(IBinder obj){
if (obj == null) {
return null;
}
IServiceManager in = (IServiceManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}
return new ServiceManagerProxy(obj);
}
public ServiceManagerNative() {
attachInterface(this, descriptor);
}
public boolean onTransact(int code, Parcel data, Parcel reply, int flags) {
......
}
......
}
class ServiceManagerProxy implements IServiceManager {
private IBinder mRemote;
public ServiceManagerProxy(IBinder remote) {
mRemote = remote;
}
......
}
这里有两个类,我们一个个看。
ServiceManagerNative
该类是ActivityManagerService的父类,而又是Binder的子类。在该构造函数中调用了attachInterface()
函数,该函数的实现在Binder
类中
frameworks/base/core/java/android/os/Binder.java:public void attachInterface(IInterface owner, String descriptor) {
mOwner = owner;
mDescriptor = descriptor;
}
这里只是正常初始化。
ServiceManagerProxy 真正调用addService函数
初始化使会传入一个IBinder接口类型。继承自IServiceManager
回到asInterface函数:
asInterface()
函数中又分为两个部分:
强转为IServiceManager类型:上述我们知道了参数进来的是BinderProxy,而
queryLocalInterface是IBinder
的接口函数。将传进来的descriptor与mDescriptor比较,若相同,说明这是进程内调用,返回mOwner。
frameworks/base/core/java/android/os/Binder.java:public IInterface queryLocalInterface(String descriptor) {
if (mDescriptor.equals(descriptor)) {
return mOwner;
}
return null;
}注意这里将
mOwner
即实现的this强转为IServiceManager类型。创建了接下来的
ServiceManagerProxy
对象,该对象实现了IServiceManager
接口。将传递的BinderProxy对象保存在了mRemote
参数中,以后面使用。这里注意
asInterface()
函数在返回是会根据in
是否为空,判断是否是进程内调用。
梳理一波
这里梳理一下前面的内容,好在能给后面的源码跟踪留下文档。
- 首先,我们知道在
android_util_Binder.cpp
中初始化了很多关于Binder的java层和Native层的桥梁参数:gBinderOffsets、gBinderInternalOffsets、gBinderProxyOffsets。 - 接着,从
ActivityManagerService
的setSystemProcess()
函数入手,进入到ServiceManager
的addService()
函数 - 在发现了
asInterface()
这个复杂的函数,他的参数是调用了android_util_Binder.cpp
文件下的android_os_BinderInternal_getContextObject()
函数中,知道了在里面创建了一个BpBinder,并且BpBinder中还有一个注意的IPCThreadState这个类。最后再创建一个新的BinderProxy对象绑定在将BpBinder中。最后返回给Java层,也即asInterface()函数的参数值。 - 在拿到BinderProxy参数后,asInterface()会判断此时是进程间通信还是跨进程通信,根据其不同返回IServiceManager或者ServiceManagerProxy。也即调用
addService
函数的真正类。
IServiceManager
上面的返回类型发现,无论是否跨进程,他都只需要IServiceManager
接口类型的返回值即可。
frameworks/native/include/binder/IServiceManager.h:class IServiceManager : public IInterface
{
public:
DECLARE_META_INTERFACE(ServiceManager);
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;
......
};
DECLARE_META_INTERFACE & IMPLEMENT_META_INTERFACE 预编译类
可以看到关键函数DECLARE_META_INTERFACE(ServiceManager)
的格式:
frameworks/native/include/binder/IInterface.h:#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() { } \
这里将ServiceManager放进去就是static const android::String16 descriptor;
static android::sp<IServiceManager> asInterface(const android::sp<android::IBinder>& obj);
virtual const android::String16& getInterfaceDescriptor() const;
IServiceManager();
virtual ~IServiceManager();
const android::String16 IServiceManager::descriptor("android.os.IServiceManager");
const android::String16& IServiceManager::getInterfaceDescriptor() const {
return IServiceManager::descriptor;
}
android::sp<IServiceManager> IServiceManager::asInterface(const android::sp<android::IBinder>& obj)
{
android::sp<IServiceManager> intr;
if (obj != NULL) {
intr = static_cast<IServiceManager *>(obj->queryLocalInterface(IServiceManager::descriptor).ge());
if (intr == NULL) {
intr = new BpServiceManager(obj)
}
}
return intr;
}
IServiceManager::IServiceManager(){}
IServiceManager::~IServiceManager(){}
在DECLARE_META_INTERFACE(INTERFACE)中
这里定义了asInterface函数、getInterfaceDescriptor函数、以及IServiceManager的构造和析构函数。在IMPLEMENT_META_INTERFACE(INTERFACE, NAME)中
函数在IServiceManager.cpp中调用IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");
实现了上述的getInterfaceDescriptor函数,asInterface函数、以及IServiceManager的构造和析构函数。
getInterfaceDescriptor()返回的即是”android.os.IServiceManager” asInterface()返回的是创建的BpServiceManager
对象,传入的参数为BpBinder(0)
的对象。
他们分别完成了定义接口和实现的功能。
BpServiceManager & BnServiceManager
这里突然又出现了这样一对类。和我们刚刚看的BpBinder & BBinder很类似。
github
BpServiceManager中mRemote参数会保存BpBinder类型数据,那么就是说BpServiceManager绑定了BpBinder类,而BpServiceManager有实现了IServiceManager接口。
addService()
在完成上述一大片代码后,终于回到了我们最开始的问题,谁调用了addService
函数。
在这里即也即实现了IServiceManager的实现类ServiceManagerProxy类
。
frameworks/base/core/java/android/os/ServiceManagerNative.java:public void addService(String name, IBinder service, boolean allowIsolated)
throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IServiceManager.descriptor);
data.writeString(name);
data.writeStrongBinder(service);
data.writeInt(allowIsolated ? 1 : 0);
mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
reply.recycle();
data.recycle();
}
之前讲过这里的mRemote是在ServiceManagerProxy类初始化的时候传入的BinderProxy
的对象。这里的data、reply为需要传输的数据包,整个过程包括初始化、写入、传递、销毁。
需要注意data.writeStrongBinder
函数,因为会将Binder
对象传进去。而transact
函数就是发送的函数
writeStrongBinder()
该函数对应与native
frameworks/base/core/jni/android_os_Parcel.cpp:static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object)
{
Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
if (parcel != NULL) {
const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
if (err != NO_ERROR) {
signalExceptionForError(env, clazz, err);
}
}
}
这里分两个部分,一个是ibinderForJavaObject
、另一个是writeStrongBinder
ibinderForJavaObject()
frameworks/base/core/jni/android_util_Binder.cpp:sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj)
{
if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {
JavaBBinderHolder* jbh = (JavaBBinderHolder*)
env->GetLongField(obj, gBinderOffsets.mObject);
return jbh != NULL ? jbh->get(env, obj) : NULL;
}
// 如果是BinderProxy类,则返回Native的BpBinder对象
if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {
return (IBinder*)
env->GetLongField(obj, gBinderProxyOffsets.mObject);
}
return NULL;
}
- 判断是否为Binder类,如果是则返回
JavaBBinderHolder
对象,并调用get
函数 - 判断是否为BinderProxy类,如果是则返回
BinderProxy
对象
这里又出来一个类:JavaBBinderHolder,他和BBinder很像。在上面我们提了一下和他相对的BpBinder。
JavaBBinderHolder
frameworks/base/core/jni/android_util_Binder.cpp:class JavaBBinderHolder : public RefBase
{
public:
sp<JavaBBinder> get(JNIEnv* env, jobject obj)
{
AutoMutex _l(mLock);
sp<JavaBBinder> b = mBinder.promote();
if (b == NULL) {
b = new JavaBBinder(env, obj);
mBinder = b;
}
return b;
}
private:
Mutex mLock;
wp<JavaBBinder> mBinder;
};
在get
函数中发现又创建了JavaBBinder对象,obj为Java层的Binder对象
JavaBBinder
|
我们终于看到了熟悉的东西BBinder
,也大致清理一下关系
github
writeStrongBinder
frameworks/base/core/jni/android_os_Parcel.cpp:status_t Parcel::writeStrongBinder(const sp<IBinder>& val) {
return flatten_binder(ProcessState::self(), val, this);
}
status_t flatten_binder(const sp<ProcessState>& /*proc*/,
const sp<IBinder>& binder, Parcel* out)
{
flat_binder_object obj;
obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
if (binder != NULL) {
// 返回BBinder对象
IBinder *local = binder->localBinder();
if (!local) {
BpBinder *proxy = binder->remoteBinder();
if (proxy == NULL) {
}
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);
}
} else {
obj.type = BINDER_TYPE_BINDER;
obj.binder = 0;
obj.cookie = 0;
}
return finish_flatten_binder(binder, obj, out);
}
inline static status_t finish_flatten_binder(
const sp<IBinder>& /*binder*/, const flat_binder_object& flat, Parcel* out)
{
return out->writeObject(flat, false);
}
这里传入的JavaBBinder继承自BBinder。因此在调用localBinder获取的是BBinder类型。
transact()
frameworks/native/libs/binder/BpBinder.cpp:status_t BpBinder::transact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
if (mAlive) {
status_t status = IPCThreadState::self()->transact(
mHandle, code, data, reply, flags);
if (status == DEAD_OBJECT) mAlive = 0;
return status;
}
return DEAD_OBJECT;
}
这里再次看到了IPCThreadState
。
IPCThreadState
真正和Binder驱动交互的是IPCThreadState
TLS为Thread Local Storage,线程本地存储空间。这些不共享的空间通过pthread_getspecific/pthread_setspecific函数获取/设置这些空间内容。我们只需要知道对于线程是相互独立的存储空间即可
frameworks/native/libs/binder/IPCThreadState.cpp:IPCThreadState::IPCThreadState()
: mProcess(ProcessState::self()),
mMyThreadId(gettid()),
mStrictModePolicy(0),
mLastTransactionBinderFlags(0)
{
// 向key:gTLS添加IPCThreadState对象
pthread_setspecific(gTLS, this);
clearCaller();
mIn.setDataCapacity(256);
mOut.setDataCapacity(256);
}
这是IPCThreadState的构造函数,每个线程都有一个IPCThreadState,每个IPCThreadState都有一个mIn、mOut,mIn是用来接收来自Binder设备的数据,而mOut则是用来存储发往Binder设备的数据。
frameworks/native/include/binder/IPCThreadState.h:class IPCThreadState
{
Parcel mIn;
Parcel mOut;
}
构造函数中将自己设置到线程本地存储。并且添加两个Parcel的缓冲区。
frameworks/native/libs/binder/IPCThreadState.cpp:IPCThreadState* IPCThreadState::self()
{
if (gHaveTLS) {
restart:
const pthread_key_t k = gTLS;
IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);
if (st) return st;
return new IPCThreadState;
}
pthread_mutex_lock(&gTLSMutex);
if (!gHaveTLS) {
if (pthread_key_create(&gTLS, threadDestructor) != 0) {
pthread_mutex_unlock(&gTLSMutex);
return NULL;
}
gHaveTLS = true;
}
pthread_mutex_unlock(&gTLSMutex);
goto restart;
}
获取到相应的IPCThreadState对象。
frameworks/native/libs/binder/IPCThreadState.cpp:status_t IPCThreadState::transact(int32_t handle,
uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags)
{
status_t err = data.errorCheck();
err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);
......
err = waitForResponse(reply);
return err;
}
最后就是transact函数,在BpBinder中调用的就是该函数。
- 在
writeTransactionData
函数的第一个参数BC_TRANSACTION
为应用程序向binder设备发送消息的消息码,而binder设备向应用程序回复消息以BR_开头。消息码定义在binder_module.h
中。
writeTransactionData
frameworks/native/libs/binder/IPCThreadState.cpp:status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,
int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer)
{
binder_transaction_data tr;
tr.target.ptr = 0; /* Don't pass uninitialized stack data to a remote process */
tr.target.handle = handle;
tr.code = code;
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) {
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.writeInt32(cmd);
mOut.write(&tr, sizeof(tr));
return NO_ERROR;
}
- binder_transaction_data是和binder设备通信的数据结构
- 这里传入的handle为0,标识目的端,0是ServiceManager的标识
- code为消息码
- flags为标记
- 最后把命令协作mOut中,但不是直接发出去
waitForResponse
frameworks/native/libs/binder/IPCThreadState.cpp: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;
......
finish:
if (err != NO_ERROR) {
if (acquireResult) *acquireResult = err;
if (reply) reply->setError(err);
mLastError = err;
}
return err;
}
这里完成发送请求数据到Binder驱动。
这里的talkWithDriver
函数需要注意,因为这里就是和Binder驱动进行数据收发的函数。
在switch中的BR_XXX就是解析来自服务器端的回应,由Binder进行回应。
executeCommand
frameworks/native/libs/binder/IPCThreadState.cpp: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_TRANSACTION:
{
binder_transaction_data tr;
result = mIn.read(&tr, sizeof(tr));
if (result != NO_ERROR) break;
Parcel buffer;
Parcel reply;
status_t error;
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 {
error = the_context_object->transact(tr.code, buffer, &reply, tr.flags);
}
}
break;
case BR_DEAD_BINDER:
{
BpBinder *proxy = (BpBinder*)mIn.readPointer();
proxy->sendObituary();
mOut.writeInt32(BC_DEAD_BINDER_DONE);
mOut.writePointer((uintptr_t)proxy);
} break;
case BR_SPAWN_LOOPER:
mProcess->spawnPooledThread(false);
break;
}
if (result != NO_ERROR) {
mLastError = result;
}
return result;
}
这里的主要工作就是解析来自Binder驱动对指定code的响应解析。
- BR_TRANSACTION:可以看到
reinterpret_cast<BBInder*>(tr.cookie)
,这里的b是BnServiceManager,因此可以将它转为BBinder类型。the_context_object是IPCThreadState.cpp中定义的全局变量,可以通过setTheContextObject函数设置。 - BR_DEAD_BINDER:收到Binder驱动发来的service死掉的消息
- BR_SPAWN_LOOPER:这里将收到来自驱动的指示以创建一个新线程,用于和Binder通信。
talkWiteDriver
那么真正和Binder驱动通信的就是上面的talkWithDriver
函数
frameworks/native/libs/binder/IPCThreadState.cpp:status_t IPCThreadState::talkWithDriver(bool doReceive)
{
binder_write_read bwr;
const bool needRead = mIn.dataPosition() >= mIn.dataSize();
const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;
bwr.write_size = outAvail;
bwr.write_buffer = (uintptr_t)mOut.data();
if (doReceive && needRead) {
bwr.read_size = mIn.dataCapacity();
bwr.read_buffer = (uintptr_t)mIn.data();
} else {
bwr.read_size = 0;
bwr.read_buffer = 0;
}
......
do {
#if defined(HAVE_ANDROID_OS)
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;
}
} while (err == -EINTR);
......
return err;
}
设置mIn数据访问的大小、长度、数据的起始地址;回应数据的大小、数据地址;然后还是与Binder驱动通行(do-while循环)ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr)
。
startThreadPool & joinThreadPool
这里就是完成上述PoolThread
线程的创建和run的功能类
startThreadPool
frameworks/native/libs/binder/ProcessState.cpp:void ProcessState::startThreadPool()
{
AutoMutex _l(mLock);
if (!mThreadPoolStarted) {
mThreadPoolStarted = true;
spawnPooledThread(true);
}
}
void ProcessState::spawnPooledThread(bool isMain)
{
if (mThreadPoolStarted) {
String8 name = makeBinderThreadName();
sp<Thread> t = new PoolThread(isMain);
t->run(name.string());
}
}
检测并开启一个threadPool。并且在调用spawnPooledThread()
时传入true参数。
这里创建了一个PoolThread
对象:
frameworks/native/libs/binder/ProcessState.cpp:class PoolThread : public Thread
{
public:
PoolThread(bool isMain)
: mIsMain(isMain) { }
protected:
virtual bool threadLoop()
{
IPCThreadState::self()->joinThreadPool(mIsMain);
return false;
}
const bool mIsMain;
};
在调用threadLoop
函数内看到了IPCThreadState
类。调用了joinThreadPool
函数。
joinThreadPool
线程调用了IPCThreadState
的joinThreadPool
函数
frameworks/native/libs/binder/IPCThreadState.cpp:void IPCThreadState::joinThreadPool(bool isMain)
{
mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
set_sched_policy(mMyThreadId, SP_FOREGROUND);
status_t result;
do {
processPendingDerefs();
int32_t cmd;
// 发送命令,读取请求
result = talkWithDriver();
if (result >= NO_ERROR) {
size_t IN = mIn.dataAvail();
if (IN < sizeof(int32_t)) return result;
cmd = mIn.readInt32();
pthread_mutex_lock(&mProcess->mThreadCountLock);
mProcess->mExecutingThreadsCount++;
pthread_mutex_unlock(&mProcess->mThreadCountLock);
// 处理消息
result = executeCommand(cmd);
......
}
......
} while (result != -ECONNREFUSED && result != -EBADF);
mOut.writeInt32(BC_EXIT_LOOPER);
talkWithDriver(false);
}
由于函数差不多,我将两个函数拼到一起。
可以看到这是一下循环状态,在不断的读取talkWithDriver
、处理executeCommand
。
梳理一波
- 首先是调用addService的类对象为
ServiceManagerProxy
,并且调用addService的类都继承了IServiceManager
。 - 我们看到
addService
函数中重要的函数writeStrongBinder
和transact
两个函数。在writeStrongBinder
中我们又发现了传递数据的是JavaBBinder
对象,也即BBinder类型;在transact
中发现最终调用的是IPCThreadState
类。 - 所以我们进入
IPCThreadState
类中,知道他是一个线程本地存储。根据self
函数知道这是一个单例,线程在ThreadState类中,他们会检查mOut是否有数据需要向BD发送。这里面存储这和服务端/客户端存储交互的mIn/mOut。而IPCThreadState,使用transact
、writeTransactionData
、talkWithDriver
、executeCommand
这一系列函数会对数据进行管理收发。
github
从上述的整个流程,也已经大致分析清楚了一点点。
github
ServiceManager
接着我们看看ServiceManager里面到底有什么。
frameworks/native/cmds/servicemanager/service_manager.c:int main(int argc, char **argv)
{
struct binder_state *bs;
// 打开Binder设备
bs = binder_open(128*1024);
// 成为manager
if (binder_become_context_manager(bs)) {
return -1;
}
selinux_enabled = is_selinux_enabled();
sehandle = selinux_android_service_context_handle();
selinux_status_open(true);
// 处理客户端发送的请求
binder_loop(bs, svcmgr_handler);
return 0;
}
来分析上述的三个函数,在最后的binder_loop
函数的参数svcmgr_handler
需要注意,他是一个函数。
binder_open()
frameworks/native/cmds/servicemanager/binder.c:struct binder_state *binder_open(size_t mapsize)
{
struct binder_state *bs;
struct binder_version vers;
bs = malloc(sizeof(*bs));
bs->fd = open("/dev/binder", O_RDWR);
bs->mapsize = mapsize;
bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
return bs;
}
- 打开binder设备
- 内存映射
binder_become_context_manager()
frameworks/native/cmds/servicemanager/binder.c:int binder_become_context_manager(struct binder_state *bs)
{
return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
}
之前我们在调用addService的时候,一直强调new BpBinder(0)
这里是设置其目的端为ServiceManager,那么这里就知道设置自己。
binder_loop()
frameworks/native/cmds/servicemanager/binder.c:void binder_loop(struct binder_state *bs, binder_handler func)
{
int res;
struct binder_write_read bwr;
uint32_t readbuf[32];
bwr.write_size = 0;
bwr.write_consumed = 0;
bwr.write_buffer = 0;
readbuf[0] = BC_ENTER_LOOPER;
binder_write(bs, readbuf, sizeof(uint32_t));
for (;;) {
bwr.read_size = sizeof(readbuf);
bwr.read_consumed = 0;
bwr.read_buffer = (uintptr_t) readbuf;
res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
// 调用了函数func
res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func);
}
}
这里看到里面是一个for的死循环,接收到请求后使用binder_parse函数调用。之前提过最后一个参数为函数svcmgr_handler
svcmgr_handler()
frameworks/native/cmds/servicemanager/service_manager.c:int svcmgr_handler(struct binder_state *bs,
struct binder_transaction_data *txn,
struct binder_io *msg,
struct binder_io *reply)
{
struct svcinfo *si;
uint16_t *s;
size_t len;
uint32_t handle;
uint32_t strict_policy;
int allow_isolated;
// 这里的BINDER_SERVICE_MANAGER是类型为uint的数字0
if (txn->target.ptr != BINDER_SERVICE_MANAGER)
return -1;
if (txn->code == PING_TRANSACTION)
return 0;
strict_policy = bio_get_uint32(msg);
s = bio_get_string16(msg, &len);
if ((len != (sizeof(svcmgr_id) / 2)) ||
memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {
fprintf(stderr,"invalid id %s\n", str8(s, len));
return -1;
}
switch(txn->code) {
case SVC_MGR_GET_SERVICE:// 得到某个service的信息,service用字符串表示
case SVC_MGR_CHECK_SERVICE:
s = bio_get_string16(msg, &len);// 表示service的名称
if (s == NULL) {
return -1;
}
handle = do_find_service(bs, s, len, txn->sender_euid, txn->sender_pid);
if (!handle)
break;
bio_put_ref(reply, handle);
return 0;
case SVC_MGR_ADD_SERVICE: // 对于addService的请求
s = bio_get_string16(msg, &len);
if (s == NULL) {
return -1;
}
handle = bio_get_ref(msg);
allow_isolated = bio_get_uint32(msg) ? 1 : 0;
if (do_add_service(bs, s, len, handle, txn->sender_euid,
allow_isolated, txn->sender_pid))
return -1;
break;
case SVC_MGR_LIST_SERVICES: { // 获取已经注册的所有service名字
uint32_t n = bio_get_uint32(msg);
if (!svc_can_list(txn->sender_pid)) {
ALOGE("list_service() uid=%d - PERMISSION DENIED\n",
txn->sender_euid);
return -1;
}
si = svclist;
while ((n-- > 0) && si)
si = si->next;
if (si) {
bio_put_string16(reply, si->name);
return 0;
}
return -1;
}
default:
return -1;
}
bio_put_uint32(reply, 0);
return 0;
}
do_add_service
在上面switch
语句中SVC_MGR_ADD_SERVICE
case看名字就知道是addService的请求,其中函数do_add_service为重要函数:
frameworks/native/cmds/servicemanager/service_manager.c:int do_add_service(struct binder_state *bs,
const uint16_t *s, size_t len,
uint32_t handle, uid_t uid, int allow_isolated,
pid_t spid)
{
struct svcinfo *si;
if (!handle || (len == 0) || (len > 127))
return -1;
// 判断是否可以注册
if (!svc_can_register(s, len, spid, uid)) {
return -1;
}
si = find_svc(s, len);
if (si) {
if (si->handle) {
ALOGE("add_service('%s',%x) uid=%d - ALREADY REGISTERED, OVERRIDE\n",
str8(s, len), handle, uid);
svcinfo_death(bs, si);
}
si->handle = handle;
} else {
si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));
if (!si) {
ALOGE("add_service('%s',%x) uid=%d - OUT OF MEMORY\n",
str8(s, len), handle, uid);
return -1;
}
si->handle = handle;
si->len = len;
memcpy(si->name, s, (len + 1) * sizeof(uint16_t));
si->name[len] = '\0';
si->death.func = (void*) svcinfo_death;
si->death.ptr = si;
si->allow_isolated = allow_isolated;
// 是一个list,用于保存当前注册到ServiceManager的信息
si->next = svclist;
svclist = si;
}
binder_acquire(bs, handle);
// 完成内存释放功能
binder_link_to_death(bs, handle, &si->death);
return 0;
}
svc_can_register
frameworks/native/cmds/servicemanager/service_manager.c:static int svc_can_register(const uint16_t *name, size_t name_len, pid_t spid, uid_t uid)
{
const char *perm = "add";
if (multiuser_get_app_id(uid) >= AID_APP) {
return 0; /* Don't allow apps to register services */
}
return check_mac_perms_from_lookup(spid, perm, str8(name, name_len)) ? 1 : 0;
}
这里会判断权限是否达标(root、system)。
添加注册服务,当然是需要有授权控制。并且会保存相应信息内容。
三、AIDL
没错,上面已经介绍完了,自己还是没看懂,代码太长,跳跃太频繁,相关类太多,而且至今连数据是什么都不知道。
而这里也是AIDL的范围,AIDL用于我们完成Binder接口通信的工具。因此在之前自己先模拟一下之前的Binder。
ServiceManager
准备ServiceManager
我们需要准备好的ServiceManager
Test.cppint main() {
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm = defaultServiceManager();
sm->addService("service.name", new Test());
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
}
准备通信内容
回想一下,我们在通信时需要服务端的BnTest和客户端代理的BpTest。但首先他们都需要一个IInterface的派生类来定义服务功能。
ITest.hclass ITest: public IInterface {
public:
DECLARE_META_INTERFACE(Test);
virtual void getTest() = 0;
virtual void setTest() = 0;
}
这里的DECLARE_META_INTERFACE
在之前说个,是一个定义I##ServiceManager
这里也即ITest
的接口功能。
当然,两个宏定义缺一不可,会在ITest.cpp文件中调用IMPLEMENT_META_INTERFACE
函数实现。
ITest.cppIMPLEMENT_META_INTERFACE(Test, "android.Test.ITest");
客户端BpTest和服务端BnTest
为了传递ITest,此时需要服务端的BnTest和服务端的BpTest。
ITest.hclass BnTest: public BnInterface<ITest> {
public:
virtual status_t onTransact(uint32 code,const Parcel& data, Parcel* reply, uint32_t flag);
}
和他的实现
ITest.cppstatus_t BnTest::onTransact(...) {
switch(code) {
case GET_Test: {
...
}
}
}
ITest.cppclass BpTest: public BpInterface<ITest> {
vitural getTest() {
Parcel data, reply;
...
remote()->transact(Get_Test, data, &reply);
return;
}
}
突然发现这些代码我们都看过了一边。这里简洁的写法更能体现代码在Binder中的重要性。
AIDL
Android Interface Definition Language 即Android接口定义语言。它依托Binder机制,使的跨进程通信能力和速度都很高。
.aidl文件
首先我们创建aidl文件,aidl文件只能调用aidl文件,也就是说我们平常创建的类需要再度封装才能在进程通信中使用。
Parcelable
这个类我们在C/C++中看到很多Parcel
,他在native层中作为进程通信的数据是重要的组成部分,我们如果需要使用,只要将它实现在我们的java类中,重写里面的方法即可。并且大部分方法都会自动重写。public class User implements Parcelable {
String name;
int age;
String sex;
public User() {
}
protected User(Parcel in) {
name = in.readString();
age = in.readInt();
sex = in.readString();
}
public static final Creator<User> CREATOR = new Creator<User>() {
@Override
public User createFromParcel(Parcel in) {
return new User(in);
}
@Override
public User[] newArray(int size) {
return new User[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(age);
dest.writeString(sex);
}
// 在实现过程中并不会重写该函数。这里也没有Override的标签
public void readFromParcel(Parcel reply) {
name = reply.readString();
age = reply.readInt();
sex = reply.readString();
}
}
这样我们就可以在aidl文件中添加这个类,并在跨进程中使用它了。这里需要注意readFromParcel
函数,因为它并没有Override的标签,在实现的时候它并不存在,稍后在介绍。
.aidl文件
在将java对象准备好后,我们就可以创建aidl文件了。这里有一类是专门为上述类做定义的,还有一类是专门为接口做定义的。
既然是通讯,自然有两端:服务端和客户端,而数据流则会有从Client到Service;Client到Service后,再传回Client。
传输对象
在准备传输对象知道首先需要实现Parcelable
,然后在aidl文件中引用它:
User.aidl:package com.test.yang.binderdemo;
// 这里就是引用了Java层的User到aidl文件中
parcelable User;
除基本类型外,我们都需要如此来添加自定义类。
接口准备
这些接口就是需要的业务功能。
ITest.aidl:package com.test.yang.binderdemo;
import com.test.yang.binderdemo.User;
interface ITest {
void setUser(out User user);
User getUser(in User a);
void inOutUser(inout User a);
}
首先是引用的User
包名需要手写;另外在添加的接口函数中形参的前面有in
、out
、inout
三种类型,in
表示数据从客户端流入服务端的数据,也是我们使用的默认类型,如果在服务端修改了这个对象的数据,在客户端是不会知道的(值不变);out
表示与in
相反的功能,在传入到服务端后,如果服务端对其内容进行修改,return后会再次流回到客户端,并且修改后的数据也会返回;inout
即上述的合并版本。
完成上述功能后,build
项目,就会得到给我们写好的java代码:
github
可以看到很多我们之前见过的代码
继承自IInterface
Stub继承自Binder和ITest,会实现asInterface和onTransact函数,而asInterface函数会创建一个内部类Proxy,也上述的ServiceManagerProxy一模一样
Proxy实现了ITest,这里就会写入该真正功能,而功能又和上述类似,使用了Parcel来包装数据,使用remote来调用onTransact函数,使其与IPC交互。
服务端
创建Service
首先需要创建一个Service
TestService.java:public class TestService extends Service {
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
准备ITest服务
准备我们监听的Stub对象:
TestService.java:...
@Override
public IBinder onBind(Intent intent) {
return stub;
}
public static ITest.Stub stub = new ITest.Stub() {
@Override
public void setUser(User user) throws RemoteException {
user.name = "C";
user.age = 31;
user.sex = "V";
}
@Override
public User getUser(User a) throws RemoteException {
return a;
}
@Override
public void inOutUser(User a) throws RemoteException {
a.age = 13333;
a.sex = "a";
}
};
记住我们aidl接口中的形参流向:in、out、inout。数据在从Client流进来修改后会被返回给客户端。完成进程间通信机制。
注册服务Action
AndroidManifest.xml:<service android:name=".TestService">
<intent-filter>
<action android:name="com.test.yang.binderdemo"/>
</intent-filter>
</service>
Activity:Intent i = new Intent(this, TestService.class);
i.setAction("com.test.yang.binderdemo");
startService(i);
以上,服务端就准备好了。
客户端
同样,完成User类的实现,aidl文件的编写,代码build生成ITest.java文件。
ServiceConnection
进入客户端:
Activity:......
private ITest iTest;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent();
intent.setPackage("com.test.yang.binderdemo");
intent.setAction("com.test.yang.binderdemo");
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
}
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
iTest = ITest.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
iTest = null;
}
};
可以看到我们调用asInterface获取类的代理。
使用
在获取到服务端的代理后,我们就可以直接使用了:
Activity.java:.....
public void onOne(View view) {
User user = new User();
user.name = "a";
user.age = 12;
try {
iTest.getUser(user);
} catch (RemoteException e) {
e.printStackTrace();
}
}
public void onTwo(View view) {
User user = new User();
try {
iTest.setUser(user);
} catch (RemoteException e) {
e.printStackTrace();
}
}
public void onThree(View view) {
User user = new User();
user.name = "b";
try {
iTest.inOutUser(user);
} catch (RemoteException e) {
e.printStackTrace();
}
}
以上就是AIDL的功能调试了,也是整个文件的结束。