`
isiqi
  • 浏览: 16484613 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类
最新评论

Android JAVA Binder IPC System

阅读更多

Binder system runs in native environment, not in JAVA VM. So for JAVA VM, it needs some JNI native implementation which lies in libs/android_runtime/android_util_Binder.cpp.

Get IServiceManager

ServiceManager.java manages all JAVA layer services. Any call in ServiceManager.java will first get a JAVA IServiceManager interface.

private static IServiceManager getIServiceManager() {

if (sServiceManager != null) {

return sServiceManager;

}

// Find the service manager

sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());

return sServiceManager;

}

BinderInternal.getContextObject is a JNI native function named android_os_BinderInternal_getContextObject. It calls into C++ layer binder system to get an IBinder(Actually it points a C++ layer BpServiceManager object), then call javaObjectForIBinder to create a corresponding JAVA class to represent the C++ IBinder object.

static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)

{

sp b = ProcessState::self()->getContextObject(NULL);

return javaObjectForIBinder(env, b);

}

javaObjectForIBinder will determine whether the object is the service provider or a service user. In getIServiceManager scenario, the object is a service user. So it will new a JAVA BinderProxy object to represent the C++ IBinder object.

jobject javaObjectForIBinder(JNIEnv* env, const sp& val)

{

object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);

if (object != NULL) {

LOGV("objectForBinder %p: created new %p!\n", val.get(), object);

// The proxy holds a reference to the native object.

env->SetIntField(object, gBinderProxyOffsets.mObject, (int)val.get());

val->incStrong(object);

// The native object needs to hold a weak reference back to the

// proxy, so we can retrieve the same proxy if it is still active.

jobject refObject = env->NewGlobalRef(

env->GetObjectField(object, gBinderProxyOffsets.mSelf));

val->attachObject(&gBinderProxyOffsets, refObject,

jnienv_to_javavm(env), proxy_cleanup);

// Note that a new object reference has been created.

android_atomic_inc(&gNumProxyRefs);

incRefsCreated(env);

}

return object;

}

Okay, now we have a JAVA BinderProxy object. Then ServiceManagerNative.asInterface will new a ServiceManagerProxy on the BinderProxy object.

static public IServiceManager asInterface(IBinder obj)

{

return new ServiceManagerProxy(obj);

}

So getIServiceManager call finally returns a ServiceManagerProxy instance.

Service create

When any JAVA service object(derived from Binder) is created, it will call init native function which points to android_os_Binder_init. Here it will new an JavaBBinderHolder, which will be used later.

static void android_os_Binder_init(JNIEnv* env, jobject clazz)

{

JavaBBinderHolder* jbh = new JavaBBinderHolder(env, clazz);

if (jbh == NULL) {

jniThrowException(env, "java/lang/OutOfMemoryError", NULL);

return;

}

LOGV("Java Binder %p: acquiring first ref on holder %p", clazz, jbh);

jbh->incStrong(clazz);

env->SetIntField(clazz, gBinderOffsets.mObject, (int)jbh);

}

Add service RPC call

Any JAVA layer service should call IServiceManager.addService API to register itself. IServiceManager.addService equals to ServiceManagerProxy.addService.

public void addService(String name, IBinder service)

throws RemoteException {

Parcel data = Parcel.obtain();

Parcel reply = Parcel.obtain();

data.writeInterfaceToken(IServiceManager.descriptor);

data.writeString(name);

data.writeStrongBinder(service);

mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);

reply.recycle();

data.recycle();

}

During in ServiceManagerProxy.addService, the JAVA service object will be written to Parcel, which finally calls a native function android_os_Parcel_writeStrongBinder.

static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jobject clazz, jobject object)

{

Parcel* parcel = parcelForJavaObject(env, clazz);

if (parcel != NULL) {

const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));

if (err != NO_ERROR) {

jniThrowException(env, "java/lang/OutOfMemoryError", NULL);

}

}

}

android_os_Parcel_writeStrongBinder call ibinderForJavaObject to generate an C++ layer IBinder object corresponding to the JavaBBinderHolder object.

sp ibinderForJavaObject(JNIEnv* env, jobject obj)

{

if (obj == NULL) return NULL;

if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {

JavaBBinderHolder* jbh = (JavaBBinderHolder*)

env->GetIntField(obj, gBinderOffsets.mObject);

return jbh != NULL ? jbh->get(env) : NULL;

}

if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {

return (IBinder*)

env->GetIntField(obj, gBinderProxyOffsets.mObject);

}

LOGW("ibinderForJavaObject: %p is not a Binder object", obj);

return NULL;

}

JavaBBinderHolder will finally new a JavaBBinder instance.

sp get(JNIEnv* env)

{

AutoMutex _l(mLock);

sp b = mBinder.promote();

if (b == NULL) {

b = new JavaBBinder(env, mObject);

mBinder = b;

LOGV("Creating JavaBinder %p (refs %p) for Object %p, weakCount=%d\n",

b.get(), b->getWeakRefs(), mObject, b->getWeakRefs()->getWeakCount());

}

return b;

}

The JavaBBinder object is derived from BBinder. After ibinderForJavaObject, Android has successfully created a C++ layer BBinder object from JAVA layer service class.

ServiceManagerProxy then calls BinderProxy JNI native function android_os_BinderProxy_transact to dispatch the RPC call from JAVA to C++. In this function a C++ IBinder object(Mentioned before, actually it’s a BpServiceManager object) corresponding to the JAVA BinderProxy object is gotten, which is originally saved in javaObjectForIBinder.

static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,

jint code, jobject dataObj,

jobject replyObj, jint flags)

{

IBinder* target = (IBinder*)

env->GetIntField(obj, gBinderProxyOffsets.mObject);

if (target == NULL) {

jniThrowException(env, "java/lang/IllegalStateException", "Binder has been finalized!");

return JNI_FALSE;

}

status_t err = target->transact(code, *data, reply, flags);

if (err == NO_ERROR) {

return JNI_TRUE;

} else if (err == UNKNOWN_TRANSACTION) {

return JNI_FALSE;

}

signalExceptionForError(env, obj, err);

return JNI_FALSE;

}

Okay, until now. Android have successfully send RPC call from JAVA layer to C++ layer. The RPC call will be handled by service_manager process. The C++ layer’s handling is another story, which won’t be included in this topic.You can refer to my C++ layer Binder system introduction.

Get ISensorService

The only way to get an interface is through IServiceManager.getService. Just like the process of IServiceManager.addService, the RPC call is sent from JAVA ServiceManagerProxy to C++ BpServiceManager. BpServiceManager finally delivers the call to service_manager process. After service_manager process this RPC call, BpServiceManager will continue executing. The returned C++ IBinder object actually is a BpBinder instance.

virtual sp getService(const String16& name) const

{

unsigned n;

for (n = 0; n < 5; n++){

sp svc = checkService(name);

if (svc != NULL) return svc;

LOGI("Waiting for sevice %s...\n", String8(name).string());

sleep(1);

}

return NULL;

}

virtual sp 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();

}

Then ServiceManagerProxy will get executed after transact, it calls a JNI native function android_os_Parcel_readStrongBinder. android_os_Parcel_readStrongBinder will call javaObjectForIBinder to generate a JAVA object for the returned C++ IBinder object.

static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jobject clazz)

{

Parcel* parcel = parcelForJavaObject(env, clazz);

if (parcel != NULL) {

return javaObjectForIBinder(env, parcel->readStrongBinder());

}

return NULL;

}

javaObjectForIBinder will determine whether the object is the service provider or a service user. In this scenario, the object is a service user. So it will new a JAVA BinderProxy object to represent the C++ IBinder object just like the scenario to get IServiceManager. Okay, now we have a JAVA BinderProxy object. Then ISensorService.Stub.asInterface will new a ISensorService.Stub.Proxy on the BinderProxy object.

/**

* Cast an IBinder object into an ISensorService interface,

* generating a proxy if needed.

*/

public static android.hardware.ISensorService asInterface(android.os.IBinder obj)

{

if ((obj==null)) {

return null;

}

android.hardware.ISensorService in = (android.hardware.ISensorService)obj.queryLocalInterface(DESCRIPTOR);

if ((in!=null)) {

return in;

}

return new android.hardware.ISensorService.Stub.Proxy(obj);

}

So we finally get an ISensorService.Stub.Proxy instance.

ISensorService.reportAccuracy RPC Call

It equals to call ISensorService.Stub.Proxy.reportAccuracy. The corresponding code is generated by aidl. It calls BinderProxy JNI native function android_os_BinderProxy_transact to dispatch the RPC call from JAVA to C++. Okay, until now. Android have successfully send RPC call from JAVA layer to C++ layer.

Handle ISensorService.reportAccuracy RPC Call

The RPC call will be first handled by C++ JavaBBinder object (This step is introduced in my Binder system introduction.), which is generated during IServiceManager.addService call.

virtual status_t onTransact(

uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0)

{

JNIEnv* env = javavm_to_jnienv(mVM);

jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,

code, (int32_t)&data, (int32_t)reply, flags);

jthrowable excep = env->ExceptionOccurred();

if (excep) {

report_exception(env, excep,

"*** Uncaught remote exception! "

"(Exceptions are not yet supported across processes.)");

res = JNI_FALSE;

/* clean up JNI local ref -- we don't return to Java */

env->DeleteLocalRef(excep);

}

JavaBBinder will call JAVA layer’s function through JNI. The function is Binder.executeTransact.

private boolean execTransact(int code, int dataObj, int replyObj,

int flags) {

Parcel data = Parcel.obtain(dataObj);

Parcel reply = Parcel.obtain(replyObj);

// theoretically, we should call transact, which will call onTransact,

// but all that does is rewind it, and we just got these from an IPC,

// so we'll just call it directly.

boolean res;

try {

res = onTransact(code, data, reply, flags);

} catch (RemoteException e) {

reply.writeException(e);

res = true;

} catch (RuntimeException e) {

reply.writeException(e);

res = true;

}

reply.recycle();

data.recycle();

return res;

}

Finally Binder.executeTransact will call ISensorService.onTransact. ISensorService.onTransact will call SensorService.reportAccuracy to do the real work。

分享到:
评论

相关推荐

    Android 代码分析

    Android JAVA Binder IPC System是Android独有的进程间通信机制。Binder通信简介涵盖了ServiceManager进程注册、客户端获取远程服务、Binder内核交互等环节,深入分析了通信的完整流程。 Android Media Scanner ...

    Android_Binder设计与实现_-_设计篇

    尽管Linux系统已提供了丰富的IPC手段,如管道、System V IPC、socket等,但Binder因其独特优势,在Android中获得了广泛应用。深入理解Binder的设计原理及其与传统IPC的对比,对于把握进程间通信的实现细节及性能优化...

    android IPC及原理简介

    本文主要探讨Android特有的IPC机制——Binder通信,以及其与Linux系统其他IPC方式的区别。 首先,Linux系统提供了多种传统的IPC方式,如socket、命名管道(named pipe)、消息队列(message queue)、信号(signal...

    使用android的binder机制,进行RPC,使用C语言接口编程.zip

    在Android系统中,Binder机制是实现进程间通信(IPC,Inter-Process Communication)的主要手段,尤其在服务间的通信中扮演着至关重要的角色。本资料主要探讨如何利用Binder机制来进行远程过程调用(RPC,Remote ...

    Android 基于Socket 的IPC通信

    6. **Binder与AIDL**:在Android中,更常见的IPC方式是Binder和AIDL(Android Interface Definition Language)。然而,当需要跨设备或者跨网络的通信时,Socket是更合适的选择。 **示例代码** 服务端: ```java ...

    android源码中system 部分

    4. **系统库**: System层包含了多个系统库,如liblog用于日志记录,libutils提供通用工具函数,libbinder是实现Binder IPC的基础,libcutils提供了一些低级别的实用工具,libandroid_runtime则是Java运行时环境的一...

    AndroidIPC通讯机制源码分析[归类].pdf

    在Android系统中,Binder通信机制是其核心的进程间通信(IPC)方式,相较于其他Linux系统中的IPC方式如socket、named pipe、message queue等,Binder以其高效性与独特设计成为Android首选。 Binder通信依赖于Linux...

    Android_IPC

    在Android中,Binder通信机制是实现IPC的核心,它提供了一种高效、安全的方式来跨进程调用方法和传递数据。 Binder通信是基于Service与Client的概念。在Android中,每个需要进行IPC的进程都需要创建一个实现IBinder...

    AndroidIPC通讯机制源码分析.pdf

    Google选择Binder作为Android的主要IPC手段,主要原因是它的高效性和安全性。Binder通信类似于线程迁移,使得调用方仿佛在另一个进程中执行代码并直接返回结果,这种同步通信方式减少了数据复制和上下文切换的开销。...

    binder例子

    2. Binder对象:在Java层,Binder是一个接口,而在C++层,Binder是一个类,它实现了Android Framework层与Native层之间的桥梁。通过Binder,我们可以创建跨进程的对象引用,实现远程方法调用。 二、Binder工作原理 ...

    Android-System-Development_JAVA.pdf.zip_android

    13. **Android组件间通信**:Android组件间可以通过Intent进行通信,也可以通过Binder机制实现进程间通信(IPC)。 14. **Material Design**:谷歌推出的Material Design设计规范为Android应用提供了统一的视觉风格...

    android aidl 之 system service 架构

    在Android系统中,AIDL(Android Interface Definition Language)是一种强大的工具,用于实现进程间通信(IPC,Inter-Process Communication)。System Service是Android操作系统的核心组成部分,它们是系统级服务...

    Android IPC介绍

    在深入探讨Android的IPC(Inter-Process Communication,进程间通信)机制之前,有必要先了解Binder通信的基础概念及其重要性。 Linux系统中,进程间通信的方式主要包括:socket、named pipe、message queue、...

    Binder 测试Demo客户端

    在Android系统中,Binder是进程间通信(IPC, Inter-Process Communication)的主要机制,它使得应用程序之间能够共享数据和服务。本教程将深入讲解基于Binder的客户端实现,即"Binder测试Demo客户端"。在这个Demo中...

    Android-system-architecture-.rar_android

    这些服务通过Binder IPC机制进行通信,构成了Android系统的基础框架。 五、应用程序框架 应用程序框架提供了一系列API,让开发者可以创建各种应用程序。包括Activity管理、Content Provider、Intent机制、Broadcast...

    王家林的Android系统完整训练:开发搭载Android系统的产品

    这门课程特别关注Android的五大核心组件:Hardware Abstract Layer(HAL)、Binder、Native Service、Android Service以及View System,并以此为基础,帮助学员全面理解和掌握Android系统的精髓。 1. **Hardware ...

    Android技术内幕.系统卷(扫描版)

    第3章 android的ipc机制--binder /100 3.1 binder概述 /101 3.1.1 为什么选择binder /101 3.1.2 初识binder /102 3.2 binder驱动的原理和实现 /102 3.2.1 binder驱动的原理 /102 3.2.2 binder驱动的实现 /103 3.3 ...

    hook_binder

    Binder是Android系统中进程间通信(IPC)的主要机制,它允许应用程序和服务之间安全地交换数据。Binder通信涉及服务代理、客户端代理、以及Binder驱动等多个组件,这些组件协同工作以实现跨进程的数据传输。 `...

    Android架构剖析和机能分析

    Binder是Android独特的IPC方式,它允许不同进程之间的对象交互,通过AIDL(Android Interface Definition Language)定义接口,实现跨进程调用。Binder具有高效性,因为它使用共享内存来减少数据复制,并通过引用...

Global site tag (gtag.js) - Google Analytics