作者 | 刘望舒

本文经授权转载自后厂技术官(ID:houchangcto)

责编 | 胡巍巍

在shu.cn/framework/binder/3-addservice.html 这篇文章中,我介绍的是Native Binder中的系统服务的注册过程。

这一过程的核心是ServiceManager,而在Java Binder中,也有一个ServiceManager,只不过这个ServiceManager是Java文件。

既然要将系统服务注册到ServiceManager,那么需要选择一个系统服务为例,这里以常见的AMS为例。

将AMS注册到ServiceManager

在AMS的setSystemProcess方法中,会调用ServiceManager的addService方法,如下所示。

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

    public void setSystemProcess() {try {ServiceManager.addService(Context.ACTIVITY_SERVICE, this, /* allowIsolated= */ true,DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_NORMAL | DUMP_FLAG_PROTO);//1....} catch (PackageManager.NameNotFoundException e) {throw new RuntimeException("Unable to find android system package", e);}...}

注释1处的Context.ACTIVITY_SERVICE的值为"activity",作用就是将AMS注册到ServiceManager中。接着来看ServiceManager的addService方法。
frameworks/base/core/java/android/os/ServiceManager.java

    public static void addService(String name, IBinder service, boolean allowIsolated,int dumpPriority) {try {getIServiceManager().addService(name, service, allowIsolated, dumpPriority);} catch (RemoteException e) {Log.e(TAG, "error in addService", e);}}

主要分析getIServiceManager方法返回的是什么,代码如下所示。
frameworks/base/core/java/android/os/ServiceManager.java

   private static IServiceManager getIServiceManager() {if (sServiceManager != null) {return sServiceManager;}sServiceManager = ServiceManagerNative.asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));return sServiceManager;}

讲到这里,已经积累了几个点需要分析,分别是:

  • BinderInternal.getContextObject()

  • ServiceManagerNative.asInterface()

  • getIServiceManager().addService()

现在我们来各个击破它们。

1.1 BinderInternal.getContextObject()

Binder.allowBlocking的作用是将BinderProxy的sWarnOnBlocking值置为false。

主要来分析BinderInternal.getContextObject()做了什么,这个方法是一个Native方法,找到它对应的函数:

frameworks/base/core/jni/android_util_Binder.cpp

static const JNINativeMethod gBinderInternalMethods[] = {{ "getContextObject", "()Landroid/os/IBinder;", (void*)android_os_BinderInternal_getContextObject },...
};

对应的函数为android_os_BinderInternal_getContextObject:

frameworks/base/core/jni/android_util_Binder.cpp

static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{sp<IBinder> b = ProcessState::self()->getContextObject(NULL);//1return javaObjectForIBinder(env, b);
}

ProcessState::self()的作用,是创建ProcessState,注释1处最终返回的是BpBinder。

BpBinder是Native Binder中的Client端,这说明Java层的ServiceManager需要Native层的BpBinder。

但是这个BpBinder在Java层是无法直接使用,那么就需要传入javaObjectForIBinder函数来做处理。

其内部会创建一个BinderProxy对象,这样我们得知 BinderInternal.getContextObject()最终得到的是BinderProxy。

BinderProxy是Java Binder的客户端的代表。

需要注意的一点是,这个传入的BpBinder会保存到BinderProxy的成员变量mObject中,后续会再次提到这个点。

1.2 ServiceManagerNative.asInterface()

说到asInterface方法,在Native Binder中也有一个asInterface函数,它的作用是用BpBinder做为参数创建BpServiceManager。

那么在Java Binder中的asInterface方法的作用又是什么?

frameworks/base/core/java/android/os/ServiceManagerNative.java

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

根据1.1小节,我们得知obj的值为BinderProxy,那么asInterface方法的作用就是用BinderProxy作为参数创建ServiceManagerProxy。

BinderProxy和BpBinder分别在Jave Binder和Native Binder作为客户端的代表,BpServiceManager通过BpBinder来实现通信、

同样的,ServiceManagerProxy也会将业务的请求交给BinderProxy来处理。分析到这里,那么:

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

可以理解为:

        sServiceManager = new ServiceManagerProxy(BinderProxy);}

1.3 getIServiceManager().addService()

根据1.2节的讲解,getIServiceManager()返回的是ServiceManagerProxy。

ServiceManagerProxy是ServiceManagerNative的内部类,它实现了IServiceManager接口。

来查看ServiceManagerProxy的addService方法,

frameworks/base/core/java/android/os/ServiceManagerNative.java::ServiceManagerProxy

    public void addService(String name, IBinder service, boolean allowIsolated, int dumpPriority)throws RemoteException {Parcel data = Parcel.obtain();Parcel reply = Parcel.obtain();data.writeInterfaceToken(IServiceManager.descriptor);data.writeString(name);data.writeStrongBinder(service);//1data.writeInt(allowIsolated ? 1 : 0);data.writeInt(dumpPriority);mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);//2reply.recycle();data.recycle();}

注释1处的data.writeStrongBinder很关键,后续会进行分析。这里又看到了Parcel,它是一个数据包装器,将请求数据写入到Parcel类型的对象data中。

通过注释1处的mRemote.transact发送出去,mRemote实际上是BinderProxy,BinderProxy.transact是native函数,实现的函数如下所示。

frameworks/base/core/jni/android_util_Binder.cpp

static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException
{if (dataObj == NULL) {jniThrowNullPointerException(env, NULL);return JNI_FALSE;}Parcel* data = parcelForJavaObject(env, dataObj);//1if (data == NULL) {return JNI_FALSE;}Parcel* reply = parcelForJavaObject(env, replyObj);//2if (reply == NULL && replyObj != NULL) {return JNI_FALSE;}IBinder* target = getBPNativeData(env, obj)->mObject.get();//3if (target == NULL) {jniThrowException(env, "java/lang/IllegalStateException", "Binder has been finalized!");return JNI_FALSE;}...status_t err = target->transact(code, *data, reply, flags);//4return JNI_FALSE;
}

注释1和注释2处,将Java层的Parcel对象转化成为Native层的Parcel对象。在1.1小节中,我们得知BpBinder会保存到BinderProxy的成员变量mObject中,因此在注释3处,从BinderProxy的成员变量mObject中获取BpBinder。

最终会在注释4处调用BpBinder的transact函数,向Binder驱动发送数据,可以看出Java Binder是需要Native Binder支持的,最终的目的就是向Binder驱动发送和接收数据。

引出JavaBBinder

接着回过头来分析1.3小节遗留下来的data.writeStrongBinder(service),代码如下所示。

frameworks/base/core/java/android/os/Parcel.java

  public final void writeStrongBinder(IBinder ll) {nativeWriteStrongBinder(mNativePtr, val);}

nativeWriteStrongBinder是Native方法,实现的函数为android_os_Parcel_writeStrongBinder: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));//1if (err != NO_ERROR) {signalExceptionForError(env, clazz, err);}}
}

接着查看注释1处ibinderForJavaObject函数:frameworks/base/core/jni/android_util_Binder.cpp

sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj)
{if (obj == NULL) return NULL;if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {//1JavaBBinderHolder* jbh = (JavaBBinderHolder*)env->GetLongField(obj, gBinderOffsets.mObject);return jbh->get(env, obj);//2}if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {return getBPNativeData(env, obj)->mObject;}ALOGW("ibinderForJavaObject: %p is not a Binder object", obj);return NULL;
}

注释2处,如果obj是Java层的BinderProxy类,则返回BpBinder。注释1处,如果obj是Java层的Binder类,那么先获取JavaBBinderHolder对象,然后在注释2处调用JavaBBinderHolder的get函数,代码如下所示。frameworks/base/core/jni/android_util_Binder.cpp::JavaBBinderHolder

class JavaBBinderHolder
{
public:sp<JavaBBinder> get(JNIEnv* env, jobject obj){AutoMutex _l(mLock);sp<JavaBBinder> b = mBinder.promote();//1if (b == NULL) {//obj是一个Java层Binder对象b = new JavaBBinder(env, obj);//2mBinder = b;ALOGV("Creating JavaBinder %p (refs %p) for Object %p, weakCount=%" PRId32 "\n",b.get(), b->getWeakRefs(), obj, b->getWeakRefs()->getWeakCount());}return b;}sp<JavaBBinder> getExisting(){AutoMutex _l(mLock);return mBinder.promote();}
private:Mutex           mLock;wp<JavaBBinder> mBinder;
};

成员变量mBinder是wp<JavaBBinder>类型的弱引用,在注释1处得到sp<JavaBBinder>类型的强引用b,在注释2处创建JavaBBinder并赋值给b。那么,JavaBBinderHolder的get函数返回的是JavaBBinder。

data.writeStrongBinder(service)在本文中等价于:

data.writeStrongBinder(new JavaBBinder(env,Binder))。

讲到这里可以得知ServiceManager.addService()传入的并不是AMS本身,而是JavaBBinder。

解析JavaBBinder

接着来分析JavaBBinder,查看它的构造函数:

frameworks/base/core/jni/android_util_Binder.cpp::JavaBBinderHolder::JavaBBinder

class JavaBBinder : public BBinder
{
public:JavaBBinder(JNIEnv* env, jobject /* Java Binder */ c): mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object)){ALOGV("Creating JavaBBinder %p\n", this);gNumLocalRefsCreated.fetch_add(1, std::memory_order_relaxed);gcIfManyNewRefs(env);}
...

可以发现JavaBBinder继承了BBinder,那么JavaBBinder的作用是什么呢?

当Binder驱动得到客户端的请求,紧接着会将响应发送给JavaBBinder,这时会调用JavaBBinder的onTransact函数,代码如下所示:frameworks/base/core/jni/android_util_Binder.cpp::JavaBBinderHolder::JavaBBinder

 virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0){                            JNIEnv* env = javavm_to_jnienv(mVM);ALOGV("onTransact() on %p calling object %p in env %p vm %p\n", this, mObject, env, mVM);IPCThreadState* thread_state = IPCThreadState::self();const int32_t strict_policy_before = thread_state->getStrictModePolicy();jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,code, reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(reply), flags);//1...return res != JNI_FALSE ? NO_ERROR : UNKNOWN_TRANSACTION;}

在注释1处会调用Java层Binder的execTransact函数:

frameworks/base/core/java/android/os/Binder.java

    private boolean execTransact(int code, long dataObj, long replyObj,int flags) {
...try {if (tracingEnabled) {Trace.traceBegin(Trace.TRACE_TAG_ALWAYS, getClass().getName() + ":" + code);}res = onTransact(code, data, reply, flags);//1} catch (RemoteException|RuntimeException e) {...}...return res;}

关键点是注释1处的onTransact函数,AMS实现了onTransact函数,从而完成业务实现。

从这里可有看出,JavaBBinder并没有实现什么业务,当它接收到请求时,会调用Binder类的execTransact函数,execTransact函数内部又调用了onTransact函数,系统服务会重写onTransact函数来实现自身的业务功能。

Java Binder架构

Binder架构如下图所示。

Native Binder的部分在此前的文章已经讲过,这里主要来说说Java Binder部分,从图中可以看到:

1.Binder是服务端的代表,JavaBBinder继承BBinder,JavaBBinder通过mObject变量指向Binder。

2.BinderProxy是客户端的代表,ServiceManager的addService等方法会交由ServiceManagerProxy处理。

3.ServiceManagerProxy的成员变量mRemote指向BinderProxy对象,所以ServiceManagerProxy的addService等方法会交由BinderProxy来处理。

4.BinderProxy的成员变量mObject指向BpBinder对象,因此BinderProxy可以通过BpBinder和Binder驱动发送数据。

感谢:
《深入理解Android卷二》
《深入理解Android卷三》
http://gityuan.com/2015/11/21/binder-framework/

【END】

热 文 推 荐 

开发者在行动!中国防疫开源项目登上GitHub TOP榜

延迟上班别发愁,远程办公抗疫情!

☞华为百度美团驰援抗击疫情;自由软件基金会建议开源 Windows 7;印度超越美国成第二大智能手机市场 | 极客头条

疫情严重,潜伏期也有传染性?科技公司在行动

☞程序员谈从科比的曼巴精神中,我们能学到什么?

你点的每个在看,我都认真当成了喜欢

大厂爱考的 Binder 系统服务注册问题怎么破?相关推荐

  1. 2022年最新的Android面试大厂必考174题(附带详细答案)

    前言 互联网行业竞争也越来残酷,我们工程师只有不断地学习,提升自己的能力才更保障你拿到更好的薪水,进入理想的企业(阿里.字节.腾讯.美团 等等-) 但目前很多人出现了一系列的疑惑问题就是: 以你目前的 ...

  2. 分布式系统服务注册与发现原理 SpringCloud 学习笔记

    分布式系统服务注册与发现原理 & SpringCloud 学习笔记 分布式系统服务注册与发现原理 引入服务注册与发现组件的原因 单体架构 应用与数据分离 集群部署 微服务架构 架构演进总结 服 ...

  3. (一)梳理前端知识体系,搞定大厂必考面试题

    梳理前端知识体系,搞定大厂必考面试题 常见面试题 JS基础知识 变量类型和计算 原型和原型链 作用域和闭包 异步和单线程 运行环境 HTTP协议 总结 常见面试题 JS基础知识 变量类型和计算 typ ...

  4. 「 最新大厂常考架构技术面试题 + 详细解答」

    很多没有收到offer的朋友一直在 后台问我,怎么梳理面试要考的知识点.这里必须要和大家再强调一下要准备的7大方面!总结起来包括:JAVA编程语言+数据结构和算法题+计网+操作系统+设计模式+数据库+ ...

  5. 分布式系统服务注册与发现概念和原理

    在微服务架构或分布式环境下,服务注册与发现技术不可或缺,这也是程序员进阶之路必须要掌握的核心技术之一,本文通过图解的方式带领大家轻轻松松掌握. 引入服务注册与发现组件的原因 先来看一个问题,假如现在我 ...

  6. 最全Java面试208题,涵盖大厂必考范围!强烈建议收藏~

    这些题目是去百度.小米.乐视.美团.58.猎豹.360.新浪.搜狐等一线互联网公司面试被问到的题目,熟悉本文中列出的知识点会大大增加通过前两轮技术面试的几率. 一.java基础面试知识点 java中= ...

  7. Android Binder机制情景源码分析之Binder回调注册和反注册

    我们在日常开发中,经常用到Binder来进行跨进程通信,有个比较常见的场景是向服务端注册Binder回调,比如: IActivityManager中有两个成对的方法,Client端向AMS所在的服务端 ...

  8. linux 如何注册服务,Linux 系统服务注册

    Linux注册系统服务步骤 1.编写服务脚本 2.拷贝到/etc/init.d目录下 3.为服务脚本添加可执行权限   >>chmod a+x xxxd 4.添加到系统服务中        ...

  9. 13张图解分布式系统服务注册与发现机制,给你整明白

    本文 Github/javamap 已收录,有Java程序员进阶技术知识地图以及我的系列文章,欢迎大家Star. 在微服务架构或分布式环境下,服务注册与发现技术不可或缺​,这也是程序员进阶之路必须要掌 ...

最新文章

  1. Java 利用反射实现C#的委托
  2. stl取出字符串中的字符_从C ++ STL中的字符串访问字符元素
  3. maven配置sqlServer的依赖
  4. opencv-api minEnclosingCircle
  5. 直接上手!不容错过的 Visual Studio Code 十大扩展组件
  6. python的jieba分词
  7. 双系统下卸载linux系统
  8. mysql 无法连接 native_php无法连接mysql8 mysql_native_password
  9. 小鹤双拼学习指引-by小鹤双拼作者-散步的鹤
  10. “杀京东”京东价格监控软件项目开发日志一
  11. 阿里云ECS训练营Class6
  12. 从雀书无代码应用——浅谈零代码开发平台(上)
  13. C++链表偶数在前,奇数在后的简单方法
  14. [树的直径 树形DP] UOJ #11【UTR #1】ydc的大树
  15. Python判断指定日期是不是法定节假日
  16. P02014158 马帅(信息论课程作业)
  17. 专用神经网络处理器的芯片,cpu可以跑神经网络吗
  18. 郑大计算机研究生学硕好还是专硕好,2021郑州大学考研:学硕专硕的区别
  19. git拉取远程分支代码到本地并关联分支
  20. 【IoT】13.Disruptive Innovation 开拓式创新

热门文章

  1. 如何使用 淘宝 NPM 镜像
  2. AJAX请求 $.post方法的使用
  3. 第六章:fusionChart的例子
  4. 经典SQL语句集锦(收藏版)
  5. PaddlePaddle中内置数据集分析
  6. Ambari--告警管理
  7. HDU.1005 Number Sequence
  8. 现代C++模板元编程基础
  9. Qt与HTML/JavaScript网页端通信和调用
  10. unity_AR(一) 安卓手机无法显示模型和无法播放动画问题