转自:https://blog.csdn.net/moonshine2016/article/details/54378358

参考:https://www.jianshu.com/p/9c023701c261

几天前一个同事问Java层的Binder和Java层的ServiceManager和C++层的ServiceManager是如何对应起来的,竟然一时语噻,一段时间不关注就会感到陌生啊,现在再总结一下,只写Java层的,C++层的不写,C++ Binder的知识需掌握,java和native的基本概念及对应关系不讲。

Java层Binder的初始化过程

Binder最终是要和它的驱动打交道,Java层要调Linux内核层的东西必然要通过native方法,而对于android的系统服务,native和java的对应,总会有一个注册过程,先看这个注册是在哪实现的

JNI Binder的注册

Zygote在启动时:

app_main.cpp

int main(int argc, char* const argv[])

{

......

AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));

......

if (zygote) {

runtime.start("com.android.internal.os.ZygoteInit", args, zygote);

}

......

}

AppRuntime是AndroidRuntime的子类,它本身没有覆盖start方法,所以要去看AndroidRuntime类中的start方法

void AndroidRuntime::start(const char* className, const Vector& options, bool zygote)

{

......

/*

* Register android functions.

*/

if (startReg(env) < 0) {

ALOGE("Unable to register all android natives\n");

return;

}

......

}

/*

* Register android native functions with the VM.

*/

/*static*/ int AndroidRuntime::startReg(JNIEnv* env)

{

......

if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {

env->PopLocalFrame(NULL);

return -1;

}

......

}

gRegJNI是个数组:

static const RegJNIRec gRegJNI[] = {

......

REG_JNI(register_android_os_Binder),

......

};

REG_JNI是一个宏定义

#ifdef NDEBUG

#define REG_JNI(name)      { name }

struct RegJNIRec {

int (*mProc)(JNIEnv*);

};

#else

#define REG_JNI(name)      { name, #name }

struct RegJNIRec {

int (*mProc)(JNIEnv*);

const char* mName;

};

#endif

gRegJNI是一个RegJNIRec的数组,所以gRegJNI的定义就变成了这样:

static const RegJNIRec gRegJNI[] = {

......

{ register_android_os_Binder },

......

};

register_jni_procs函数如下:

static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env)

{

for (size_t i = 0; i < count; i++) {

if (array[i].mProc(env) < 0) {

#ifndef NDEBUG

ALOGD("----------!!! %s failed to load\n", array[i].mName);

#endif

return -1;

}

}

return 0;

}

就是循环调用gRegJNI数组中的函数,这时register_android_os_Binder(env)就被调用了。

register_android_os_Binder在AndroidRuntime.cpp中被声明为extern:

extern int register_android_os_Binder(JNIEnv* env);

1

实现它的地方是在android_util_Binder.cpp中:

int register_android_os_Binder(JNIEnv* env)

{

if (int_register_android_os_Binder(env) < 0)

return -1;

if (int_register_android_os_BinderInternal(env) < 0)

return -1;

if (int_register_android_os_BinderProxy(env) < 0)

return -1;

......

return 0;

}

从名字上看,它要关联3个Java的类,分别是Binder, BinderInternal和BinderProxy,一个一个看来:

const char* const kBinderPathName = "android/os/Binder";

static int int_register_android_os_Binder(JNIEnv* env)

{

jclass clazz = FindClassOrDie(env, kBinderPathName);

gBinderOffsets.mClass = MakeGlobalRefOrDie(env, clazz);

gBinderOffsets.mExecTransact = GetMethodIDOrDie(env, clazz, "execTransact", "(IJJI)Z");

gBinderOffsets.mObject = GetFieldIDOrDie(env, clazz, "mObject", "J");

return RegisterMethodsOrDie(

env, kBinderPathName,

gBinderMethods, NELEM(gBinderMethods));

}

关联了android.os.Binder类,并会用到该类的mExecTransact域和execTransact方法,将其保存到gBinderOffsets对象中,也就意味着native会将某值保存到mExecTransact中,也会回调execTransact方法。

const char* const kBinderInternalPathName = "com/android/internal/os/BinderInternal";

static int int_register_android_os_BinderInternal(JNIEnv* env)

{

jclass clazz = FindClassOrDie(env, kBinderInternalPathName);

gBinderInternalOffsets.mClass = MakeGlobalRefOrDie(env, clazz);

gBinderInternalOffsets.mForceGc = GetStaticMethodIDOrDie(env, clazz, "forceBinderGc", "()V");

return RegisterMethodsOrDie(

env, kBinderInternalPathName,

gBinderInternalMethods, NELEM(gBinderInternalMethods));

}

关联了java的com.android.internal.os.BinderInternal类,保存了其forceBinderGc方法。

const char* const kBinderProxyPathName = "android/os/BinderProxy";

static int int_register_android_os_BinderProxy(JNIEnv* env)

{

jclass clazz = FindClassOrDie(env, "java/lang/Error");

gErrorOffsets.mClass = MakeGlobalRefOrDie(env, clazz);

clazz = FindClassOrDie(env, kBinderProxyPathName);

gBinderProxyOffsets.mClass = MakeGlobalRefOrDie(env, clazz);

gBinderProxyOffsets.mConstructor = GetMethodIDOrDie(env, clazz, "", "()V");

gBinderProxyOffsets.mSendDeathNotice = GetStaticMethodIDOrDie(env, clazz, "sendDeathNotice",

"(Landroid/os/IBinder$DeathRecipient;)V");

gBinderProxyOffsets.mObject = GetFieldIDOrDie(env, clazz, "mObject", "J");

gBinderProxyOffsets.mSelf = GetFieldIDOrDie(env, clazz, "mSelf",

"Ljava/lang/ref/WeakReference;");

gBinderProxyOffsets.mOrgue = GetFieldIDOrDie(env, clazz, "mOrgue", "J");

clazz = FindClassOrDie(env, "java/lang/Class");

gClassOffsets.mGetName = GetMethodIDOrDie(env, clazz, "getName", "()Ljava/lang/String;");

return RegisterMethodsOrDie(

env, kBinderProxyPathName,

gBinderProxyMethods, NELEM(gBinderProxyMethods));

}

这个方法比较长,保存的Java的东西也比较多,值得注意的是,它还保存了BinderProxy的构造函数,也就是说它可能会主动new一个BinderProxy实例出来。

看到目前为止,native的Binder要对应到Java的3个类中,分别是android.os.Binder,com.android.internal.os.BinderInternal和android.os.BinderProxy。为了方便阅读,将它们的对应关系以类图的形式总结下:

将Java层的服务注册到ServiceManager中的过程

我们知道,native层的Binder有Bn和Bp之说,Bn应该是Binder Native的缩写,就是本地实现Binder的意思也可以说是C/S中的S,Bp是Binder Proxy的缩写,相当于C。

以PackageManagerService为例:

public static PackageManagerService main(Context

......

PackageManagerService m = new PackageManagerService(context, installer,

factoryTest, onlyCore);

......

ServiceManager.addService("package", m);

return m;

}

public static void addService(String name, IBinder service) {

try {

getIServiceManager().addService(name, service, false);

} catch (RemoteException e) {

Log.e(TAG, "error in addService", e);

}

}

getIServiceManager返回的是一个IServiceManager类,且是个单例,最后调用的就是

private static IServiceManager getIServiceManager() {

if (sServiceManager != null) {

return sServiceManager;

}

// Find the service manager

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

return sServiceManager;

}

以上代码带来 三个问题,一个是BinderInternal.getContextObject(),一个是ServiceManagerNative.asInterface,另一个是addService的作用:

BinderInternal.getContextObject()的实质

ServiceManagerNative.asInterface中的参数是BinderInternal.getContextObject(),看它是native方法,对应的native代码就在刚刚看到的android_util_Binder.cpp文件中:

static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)

{

// 是一个BpBinder

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

return javaObjectForIBinder(env, b);

}

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

{

if (val == NULL) return NULL;

if (val->checkSubclass(&gBinderOffsets)) {

// One of our own!

jobject object = static_cast(val.get())->object();

LOGDEATH("objectForBinder %p: it's our own %p!\n", val.get(), object);

return object;

}

// For the rest of the function we will hold this lock, to serialize

// looking/creation/destruction of Java proxies for native Binder proxies.

AutoMutex _l(mProxyLock);

// Someone else's...  do we know about it?

// 1

jobject object = (jobject)val->findObject(&gBinderProxyOffsets);

if (object != NULL) {

jobject res = jniGetReferent(env, object);

if (res != NULL) {

ALOGV("objectForBinder %p: found existing %p!\n", val.get(), res);

return res;

}

LOGDEATH("Proxy object %p of IBinder %p no longer in working set!!!", object, val.get());

android_atomic_dec(&gNumProxyRefs);

val->detachObject(&gBinderProxyOffsets);

env->DeleteGlobalRef(object);

}

//2

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

if (object != NULL) {

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

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

//3

env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get());

val->incStrong((void*)javaObjectForIBinder);

// 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));

......

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

//4

android_atomic_inc(&gNumProxyRefs);

incRefsCreated(env);

}

return object;

}

首先判断下和Java层关联的Native层的BpBinder是否存在,如果存在,删除。

接着创建一个Java层的BinderProxy实例。

将Native层的BpBinder指针保存到java BinderProxy实例的mObject字段中,这样通过BinderProxy的mObject字段就可以操作Native层的BpBinder了。

原子增加gNumProxyRefs和gNumRefsCreated的数量,当gNumRefsCreated的值超过200,将会调用BinderInternal的forceBinderGc方法。

总结下:

创建了一个Native层的BpBinder;

将BpBinder的指针保存到BinderProxy的mObject,而BpBinder的通信对象就是Native的ServiceManager,这为Java和Native的ServiceManager的通信埋下了伏笔。

可以将BinderProxy说成Java层的Bp端。

ServiceManagerNative.asInterface的作用

static public IServiceManager asInterface(IBinder obj)

{

if (obj == null) {

return null;

}

//1

IServiceManager in =

(IServiceManager)obj.queryLocalInterface(descriptor);

if (in != null) {

return in;

}

//2

return new ServiceManagerProxy(obj);

}

obj是Native实例化的BinderProxy对象,BinderProxy的代码在Binder.java中,和Binder位于同一个文件中。queryLocalInterface的返回值为null。

实例化一个ServiceManagerProxy对象,该实例中有一个IBinder类型的mRemote字段,该字段保存BinderProxy实例。

public ServiceManagerProxy(IBinder remote) {

mRemote = remote;

}

总结:

ServiceManagerNative.asInterface返回的是ServiceManagerProxy的实例,该实例实现IServiceManager的接口。

ServiceManagerProxy中通过mRemote字段保存了BinderProxy,也就是Java层的Bp端。

addService的作用

有上分析,当调用ServiceManager.addService时,实际上调用的是ServiceManagerProxy类中的addService,ServiceManagerProxy类位于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);

//1

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

reply.recycle();

data.recycle();

}

mRemote即为BinderProxy,它会调用transactNative,transactNative是个native方法,接着看这个方法。

static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,

//1

IBinder* target = (IBinder*)

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

if (target == NULL) {

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

return JNI_FALSE;

}

//2

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

......

return JNI_FALSE;

}

取出保存在BinderProxy中的BpBinder对象的指针

向Native层的ServiceManager发送请求

总结:

Java层调用ServiceManger.addService后,最终是向Native层的ServiceManager请求增加服务的。

Native层的ServiceManager是只有一个的,而java层的ServiceManager相对于Native的ServiceManager也只是个C端,这样,不管是通过Native add service还是通过java add service,整个Android都可以拿到这个service的Binder。

Java Service端的Bp在哪里

这时候还有个疑问,当调用ServiceManager.addService时传入的Service应该对应到Native的BnBinder啊,现在对应关系如何体现呢?这个关系要重看下addService了。

addService第二个参数的类型是IBinder,它是个接口,而它的实现类是Binder,java上层能调用addService添加服务时,所有的实例都是Binder,根据java的规则,只要实例化,其父类的相应的构造函数必被调用:

public Binder() {

init();

......

}

init()是native方法,其实现在android_util_Binder.cpp中:

static void android_os_Binder_init(JNIEnv* env, jobject obj)

{

JavaBBinderHolder* jbh = new JavaBBinderHolder();

...

env->SetLongField(obj, gBinderOffsets.mObject, (jlong)jbh);

}

new一个native层的JavaBBinderHolder,并将其保存到Binder的mObject中。注意哦,虽然native层的gBinderOffsets.mObject是个static的,但java层的Binder的mObject可不是static的哦,就是说每个Binder实例都有一个Native的JavaBBinderHolder对象指针。

JavaBBinderHolder类的声明如下:

class JavaBBinderHolder : public RefBase

{

}

没有继承BBinder,还是没发现作为Bn端的踪影,需要再review下前面的流程,看下ServiceManagerProxy添加服务时发生了什么:

public void addService(String name, IBinder service, boolean allowIsolated)

throws RemoteException {

Parcel data = Parcel.obtain();

......

data.writeStrongBinder(service);

......

}

writeStrongBinder值得怀疑

writeStrongBinder发生了什么

Parcel的这个函数如下:

public final void writeStrongBinder(IBinder val) {

nativeWriteStrongBinder(mNativePtr, val);

}

nativeWriteStrongBinder的实现在android_os_Parcel.cpp中:

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

{

Parcel* parcel = reinterpret_cast(nativePtr);

if (parcel != NULL) {

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

if (err != NO_ERROR) {

signalExceptionForError(env, clazz, err);

}

}

}

调用了一个ibinderForJavaObject函数,该函数位于android_util_Binder.cpp中

sp ibinderForJavaObject(JNIEnv* env, jobject obj)

{

if (obj == NULL) return NULL;

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

JavaBBinderHolder* jbh = (JavaBBinderHolder*)

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

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

}

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

return (IBinder*)

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

}

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

return NULL;

}

传入的obj是Binder实例,所以刚刚创建的JavaBBinderHolder的get函数会被调用:

sp get(JNIEnv* env, jobject obj)

{

AutoMutex _l(mLock);

sp b = mBinder.promote();

if (b == NULL) {

b = new JavaBBinder(env, obj);

mBinder = b;

ALOGV("Creating JavaBinder %p (refs %p) for Object %p, weakCount=%" PRId32 "\n",

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

}

return b;

}

返回的是JavaBBinder实例,

JavaBBinder继承了BBinder,所以最终添加到Native ServiceManager中的是这个对象,总结下它们的类图:

Java层的Binder对象拥有Native JavaBBinderHolder对象的指针,JavaBBinderHolder有JavaBBinder的对象,而JavaBBinder又有Java层Binder的对象。

java层 native层_Java层的ServiceManager和Native层的ServiceManager的对应过程相关推荐

  1. java 生成https证书_java生成Https证书,及证书导入的步骤和过程

    原文参考:http://www.cnblogs.com/fron/p/https-20170111.html 以下是相关的Tomcat,JDK和Windows环境: Tomcat版本:tomcat-7 ...

  2. java逻辑层的作用_java三层架构原理与作用小结

    三层架构 三层架构(3-tier application) 通常意义上的三层架构就是将整个业务应用划分为:表现层(UI).业务逻辑层(BLL).数据访问层(DAL).区分层次的目的即为了"高 ...

  3. controll层跳转页面_java web开发中的各种层

    java后端开发前,还是应该将各种层划分好,知道各自的作用,今天做一下总结. Dao层.Entity层.Service层.Controller层.view层 1.Dao层(持久层.数据访问层) 功能: ...

  4. java弹窗点击事件_[Java教程]jQuery的click事件在当前页弹出层窗口(不打开新页面)...

    [Java教程]jQuery的click事件在当前页弹出层窗口(不打开新页面) 0 2015-10-24 15:00:04 当给链接添加一个click事件,我们可能不希望Web浏览器按照其常规模式退出 ...

  5. 表现层(jsp)、持久层(类似dao)、业务层(逻辑层、service层)、模型(javabean)、控制层(action)...

    转自:http://www.blogjava.net/jiabao/archive/2007/04/08/109189.html 为了实现web层(struts)和持久层(Hibernate)之间的松 ...

  6. 业务层 java_表现层(jsp)、持久层(类似dao)、业务层(逻辑层、service层)、模型(javabean)、控制层(action)...

    为了实现web层(struts)和持久层(Hibernate)之间的松散耦合,我们采用业务代表(Business Delegate)和DAO(Data Access Object)两种模式.DAO模式 ...

  7. 假设你有一个多层感知机网络(MLP),输入层有10个节点、一个单隐层共50个神经元,最后是一个3个神经元的输出层。请问网络的结构是什么样子的使用数学形式进行描述?

    假设你有一个多层感知机网络(MLP),输入层有10个节点.一个单隐层共50个神经元,最后是一个3个神经元的输出层.请问网络的结构是什么样子的使用数学形式进行描述? 输入矩阵X的形状是什么? 隐藏层的权 ...

  8. pcb 假八层_八层板的成本却只六层的性能,PCB设计遭遇假八层该怎么办?

    在<PCB的筋骨皮>一文中,我们提出了当板厚在1.6mm及以上时,怎样避免使用假八层的叠层,而导致PCB成本增加的问题.mb5ednc 由于大家的回答很踊跃,看来这个问题还是比较典型的.在 ...

  9. 全连接层的作用_python构建计算图2——全连接层

    (好久不更~)前文中,参照tensorflow的方式实现了简单的自动求导.接下来要在自动求导的基底(模板)上搭建简单的bp神经网络. 计算图 前文曾多次提到计算图,关于什么是计算图,有很多种说法.既然 ...

最新文章

  1. Xcode升级后插件失效的原理与修复办法
  2. 20 个最常用的 Git 命令,码住!
  3. 数据的中心化和标准化
  4. 算法学习经典例题整理
  5. sql两个表查不同数据_产品操作MySQL第6篇 – 数据过滤-WHERE子句
  6. java8 stream to map_Java 8 Stream Api 中的 map和 flatMap 操作
  7. EF+postgresql中的一些问题
  8. 把东西从学校搬回来了
  9. 充分地享受母爱的飞鸽传书
  10. 解决openfire在使用MySQL数据库后的中文乱码问题(转)
  11. java开发_读写txt文件操作
  12. thinkphp3.2 cli模式的正确使用方法
  13. GitHub上如何创建文件夹
  14. 凉凉了,Eureka 宣布闭源,Spring Cloud 何去何从? 1
  15. 统计挖掘那些事(六)——强大的逻辑回归(理论+案例)
  16. 三年经验前端社招面经——朴朴科技
  17. QFD修改工作流并重新发布中的问题
  18. 别只盯着LoRa、SigFox, LPWAN 连接技术还有这些!
  19. aps是什么意思_轿车里面的APS是什么意思 ?
  20. form表单提交时传递额外的参数

热门文章

  1. linux php jsp网页,Linux上架设支持JSP+PHP的Web服务器
  2. Import Changes from Direct3D 11 to Direct3D 12
  3. 基于 FFMPEG 的音频编解码(三):音频编码
  4. Keras-10 模型可视化
  5. 敏捷 - #1 原则:早期和持续交付有价值的软件 (#1 Agile Principle)
  6. 简单易懂设计模式——简单工厂模式
  7. 访问控制列表(二)配置命令
  8. 无法回应的ARP请求包导致的网站缓慢问题排错
  9. Halcon算子翻译——dev_close_inspect_ctrl
  10. 阐述简称PO,VO,TO,BO,DAO,POJO