ServiceManager是安卓中一个重要的类,用于管理所有的系统服务,维护着系统服务和客户端的binder通信。
对此陌生的可以先看系统服务与ServiceManager来了解应用层是如何使用ServiceManager的。
我们可以通过 ServiceManager.getService(String name)来获取服务,返回的是一个Binder对象,用于与系统做远程通信

public static IBinder getService(String name) {
try {
IBinder service = sCache.get(name);
if (service != null) {
return service;
} else {
return getIServiceManager().getService(name);
}
} catch (RemoteException e) {
Log.e(TAG, "error in getService", e);
}
return null;
}

这里的sCache是一个Map,如果cache中有这个Binder对象就直接返回了,如果没有就调用getIServiceManager().getService(name)来获取

private static IServiceManager getIServiceManager() {
if (sServiceManager != null) {
return sServiceManager;
} // Find the service manager
sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
return sServiceManager;
}

可以看到这里返回了一个IServiceManager,它也是一个Binder对象,最终获取服务用的就是这个Binder对象。
并且是通过BinderInternal.getContextObject()来拿到Binder对象的。

/**
* Return the global "context object" of the system. This is usually
* an implementation of IServiceManager, which you can use to find
* other services.
*/
public static final native IBinder getContextObject();

它实现在frameworks/base/core/jni/android_util_Binder.cpp文件中:

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

这里应该不难理解,先获取一个native层的IBinder,再将该对象转换成Java Object返回给调用者,在Java层拿到的应该是一个ServiceManagerProxy对象。
先看第一部获取native层的IBinder对象:

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

在ProcessState的构造函数中,会通过open文件操作函数打开设备文件/dev/binder,并且返回来的设备文件描述符保存在成员变量mDriverFD中,供后续在IPCThreadState中使用
需要注意的是这里传了一个NULL,也就是0,下面会提到它的作用:
[ProcessState.cpp]

sp ProcessState::getContextObject(const sp& /*caller*/)
{
return getStrongProxyForHandle();
} sp ProcessState::getStrongProxyForHandle(int32_t handle)
{
sp result; AutoMutex _l(mLock); handle_entry* e = lookupHandleLocked(handle); if (e != NULL) {
IBinder* b = e->binder;
if (b == NULL || !e->refs->attemptIncWeak(this)) {
if (handle == ) {
Parcel data;
status_t status = IPCThreadState::self()->transact(
, IBinder::PING_TRANSACTION, data, NULL, );
if (status == DEAD_OBJECT)
return NULL;
} 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;
}

可以看到,最终返回的对象是:b = new BpBinder(handle); 并将handler传了进去
这里的handler即是之前传进来的0,代表一个句柄,这个句柄是有特殊意义的。
我们知道在Java层有两类Binder,一个是Binder对象用于服务端建立的对象,一个是BinderProxy是客户端取到的Binder对象。
native层也有两类Binder,一个是BpBinder,一个是BBinder:
BpBinder是客户端用来与Server交互的代理类,p即Proxy的意思,
BBinder则是proxy交互的目的端,
并且他们是一一对应的。
继续回到代码,创建了一个BpBinder对象,传进去的hande为0,那么他是怎么找到对应的BBinder的呢?
事实上,handle代表了通信的目的端,这个0代表的就是ServiceManager所对应的BBinder。
继续往下看,通过上面获取的对象创建一个Java层的Binder对象并返回:
[android_util_Binder.cpp]

return javaObjectForIBinder(env, b)

继续看创建Java层对象的过程:
[android_util_Binder.cpp]

jobject javaObjectForIBinder(JNIEnv* env, const sp& val)
{
if (val == NULL) return NULL; if (val->checkSubclass(&gBinderOffsets)) {
// One of our own!
jobject object = static_cast<JavaBBinder*>(val.get())->object();
LOGDEATH("objectForBinder {936b63963a8c9f2b24063da536a495a32039ff9ed9d82cacc18dd4741407c351}p: it's our own {936b63963a8c9f2b24063da536a495a32039ff9ed9d82cacc18dd4741407c351}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?
jobject object = (jobject)val->findObject(&gBinderProxyOffsets);
if (object != NULL) {
jobject res = jniGetReferent(env, object);
if (res != NULL) {
ALOGV("objectForBinder {936b63963a8c9f2b24063da536a495a32039ff9ed9d82cacc18dd4741407c351}p: found existing {936b63963a8c9f2b24063da536a495a32039ff9ed9d82cacc18dd4741407c351}p!\n", val.get(), res);
return res;
}
LOGDEATH("Proxy object {936b63963a8c9f2b24063da536a495a32039ff9ed9d82cacc18dd4741407c351}p of IBinder {936b63963a8c9f2b24063da536a495a32039ff9ed9d82cacc18dd4741407c351}p no longer in working set!!!", object, val.get());
android_atomic_dec(&gNumProxyRefs);
val->detachObject(&gBinderProxyOffsets);
env->DeleteGlobalRef(object);
} object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);
if (object != NULL) {
LOGDEATH("objectForBinder {936b63963a8c9f2b24063da536a495a32039ff9ed9d82cacc18dd4741407c351}p: created new proxy {936b63963a8c9f2b24063da536a495a32039ff9ed9d82cacc18dd4741407c351}p !\n", val.get(), object);
// The proxy holds a reference to the native object.
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));
val->attachObject(&gBinderProxyOffsets, refObject,
jnienv_to_javavm(env), proxy_cleanup); // Also remember the death recipients registered on this proxy
sp drl = new DeathRecipientList;
drl->incStrong((void*)javaObjectForIBinder);
env->SetLongField(object, gBinderProxyOffsets.mOrgue, reinterpret_cast(drl.get())); // Note that a new object reference has been created.
android_atomic_inc(&gNumProxyRefs);
incRefsCreated(env);
} return object;
}

可以看到有两处返回语句,跳过第一处取缓存对象,直接往下看:

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

这里创建了一个BinderProxy对象,这时候这个对象与Native层用于通信的BpBinder没有任何关系,继续往下看:

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

这里是把BpBinder对象的地址赋值给了BinderProxy对象的mObject字段,通过这种手段将Java层的对象与Native层的对象关联在了一起。
然后我们操作Java层BinderProxy对象的native方法的时候,就能定位到对应的BpBinder对象了。
并且把这个Java层的对象放到了BpBinder对象中,之后就不用再次创建了:

jobject refObject = env->NewGlobalRef(
env->GetObjectField(object, gBinderProxyOffsets.mSelf));
val->attachObject(&gBinderProxyOffsets, refObject,
jnienv_to_javavm(env), proxy_cleanup);

回到Java层代码,我们通过下面代码来获取一个可以调用的ServiceManager对象:

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

看过Android IPC 机制的应该知道,这里返回的是一个ServiceManagerProxy对象,里面持有一个名为面Remote的IBiner对象,从上面可以看到这个mRemote就是之前拿到的BinderProxy,真正进行进程间通信的时候会调用BinderProxy的transact方法,然后在它的内部调用transactNative方法。

再次来到native层,调用如下方法:
[android_util_Binder.cpp]

static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException
{
//... IBinder* target = (IBinder*)
env->GetLongField(obj, gBinderProxyOffsets.mObject);
if (target == NULL) {
jniThrowException(env, "java/lang/IllegalStateException", "Binder has been finalized!");
return JNI_FALSE;
}
bool time_binder_calls;
int64_t start_millis;
if (kEnableBinderSample) {
time_binder_calls = should_time_binder_calls();
if (time_binder_calls) {
start_millis = uptimeMillis();
}
}
status_t err = target->transact(code, *data, reply, flags);
if (kEnableBinderSample) {
if (time_binder_calls) {
conditionally_log_binder_call(start_millis, target, code);
}
}
if (err == NO_ERROR) {
return JNI_TRUE;
} else if (err == UNKNOWN_TRANSACTION) {
return JNI_FALSE;
}
signalExceptionForError(env, obj, err, true /*canThrowRemoteException*/, data->dataSize());
return JNI_FALSE;
}

为什么是这个方法呢?这里在简单的书一下jni,有静态注册和动态注册两种方法,这里用的是动态注册,会用到如下定义:

static const JNINativeMethod gBinderProxyMethods[] = {
/* name, signature, funcPtr */
{"pingBinder", "()Z", (void*)android_os_BinderProxy_pingBinder},
{"isBinderAlive", "()Z", (void*)android_os_BinderProxy_isBinderAlive},
{"getInterfaceDescriptor", "()Ljava/lang/String;", (void*)android_os_BinderProxy_getInterfaceDescriptor},
{"transactNative", "(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z", (void*)android_os_BinderProxy_transact},
{"linkToDeath", "(Landroid/os/IBinder$DeathRecipient;I)V", (void*)android_os_BinderProxy_linkToDeath},
{"unlinkToDeath", "(Landroid/os/IBinder$DeathRecipient;I)Z", (void*)android_os_BinderProxy_unlinkToDeath},
{"destroy", "()V", (void*)android_os_BinderProxy_destroy},
};

包括Java层方法名,方法签名,调用的函数指针。
这里不过多展开了,继续:

IBinder* target = (IBinder*)env->GetLongField(obj, gBinderProxyOffsets.mObject);

可以看到这里用到了之前保存在BinderProxy中的的mObject字段,拿到了原始的BpBinder对象。
然后调用BpBinder对象的transact方法:

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

下面看BpBinder的transact方法:
[BpBinder.cpp]

tatus_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) {
status_t status = IPCThreadState::self()->transact(
mHandle, code, data, reply, flags);
if (status == DEAD_OBJECT) mAlive = ;
return status;
} return DEAD_OBJECT;
}

BpBinder只是一个转发工具,最终由IPCThreadState执行:

status_t status = IPCThreadState::self()->transact(mHandle, code, data, reply, flags);

并且带上了代表BBinder对象的mHandle。
[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();
flags |= TF_ACCEPT_FDS;
if (err == NO_ERROR) {
LOG_ONEWAY(">>>> SEND from pid {936b63963a8c9f2b24063da536a495a32039ff9ed9d82cacc18dd4741407c351}d uid {936b63963a8c9f2b24063da536a495a32039ff9ed9d82cacc18dd4741407c351}d {936b63963a8c9f2b24063da536a495a32039ff9ed9d82cacc18dd4741407c351}s", getpid(), getuid(),
(flags & TF_ONE_WAY) == ? "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) == ) {
#if 0
if (code == ) { // relayout
ALOGI(">>>>>> CALLING transaction 4");
} else {
ALOGI(">>>>>> CALLING transaction {936b63963a8c9f2b24063da536a495a32039ff9ed9d82cacc18dd4741407c351}d", code);
}
#endif
if (reply) {
err = waitForResponse(reply);
} else {
Parcel fakeReply;
err = waitForResponse(&fakeReply);
}
#if 0
if (code == ) { // relayout
ALOGI("<<<<<< RETURNING transaction 4");
} else {
ALOGI("<<<<<< RETURNING transaction {936b63963a8c9f2b24063da536a495a32039ff9ed9d82cacc18dd4741407c351}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;
}

有两个方法调用需要关注:

err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);
err = waitForResponse(NULL, NULL);

一个是写数据,一个是等待相应。在此之前假设我们知道:
每个线程都有一个IPCThreadState,每个IPCThreadState中都有一个mIn、一个mOut,其中mIn是用来接收来自Binder设备的数据的,而mOut则是用来存储发往Binder设备的数据的。
先看写数据:

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 = ; /* Don't pass uninitialized stack data to a remote process */
tr.target.handle = handle;
tr.code = code;
tr.flags = binderFlags;
tr.cookie = ;
tr.sender_pid = ;
tr.sender_euid = ;
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(statusBuffer);
tr.offsets_size = ;
tr.data.ptr.offsets = ;
} else {
return (mLastError = err);
} mOut.writeInt32(cmd);
mOut.write(&tr, sizeof(tr)); return NO_ERROR;
}

特别注意这里:tr.target.handle = handle;通信的目标值是handle,也就是之前传的0;最后写入到mOut中;
真正执行在waitForResponse方法中,这个方法是一个死循环,一直在读取mIn的数据,最后会根据code进行分发,调用executeCommand方法,
在executeCommand方法内部获取BBinder调用transact:

error = reinterpret_cast(tr.cookie)->transact(tr.code, buffer,&reply, tr.flags);

这里的mIn与mOut便是真正的进程间通信,可以查看IPCThreadState::talkWithDriver方法与Binder驱动通信,使用ioctl方式的方式读写/dev/binder虚拟设备。
关于Binder的深入分析,下次有机会再分享。
那么ServiceManager的服务是如何注册的呢?
在native层可以通过下面代码获取IServiceManager:

spsm = defaultServiceManager()

然后各个服务模块会通过IServiceManager的addService方法将各自的模块注册到系统这个唯一的ServiceManager中
[IServiceManager.cpp]

sp defaultServiceManager()
{
if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
{
AutoMutex _l(gDefaultServiceManagerLock);
while (gDefaultServiceManager == NULL) {
gDefaultServiceManager = interface_cast(
ProcessState::self()->getContextObject(NULL));
if (gDefaultServiceManager == NULL)
sleep();
}
}
return gDefaultServiceManager;
}

可以看到这个是单例,通过下面代码初始化:

gDefaultServiceManager = interface_cast(ProcessState::self()->getContextObject(NULL));

PocessState::self()->getContextObject(NULL)这个之前分析过了获取的是ServiceManager的BpBinder对象,
然后转换成BpServiceManager对象供其他服务模块使用,这里用到了模板函数和宏定义最终返回的是 new BpServiceManager(ProcessState::self()->getContextObject(NULL))。

深入理解任何Binder Client都可以直接通过ServiceManager的0这个Binder句柄创建一个BpBinde的更多相关文章

  1. 深入理解Eureka - Eureka Client获取注册信息机制

    深入理解Eureka - Eureka Client获取注册信息机 Eureka Client提供了定时获取注册信息的机制.Eureka Client获取注册信息的所有逻辑都在DiscoveryCli ...

  2. 创建一个LinkedList,然后在其中插入多个值,确保每个值都插入到List中间(偶数中间两个数之一,奇数在正中间)

    这是Thinking in java 中的一道题,下面是我的解决方案: package test; import java.util.LinkedList; import java.util.List ...

  3. Asp.Net MVC是否针对每次请求都重新创建一个控制器实例

    一.Asp.Net MVC是否针对每次请求都重新创建一个控制器实例 默认情况下,答案是确定的. ControllerBuilder类 ControllerBuilder.Current用户获取默认的控 ...

  4. 【helm & Tiller】报错Error: incompatible versions client[v2.14.1] server[v2.13.0] │

    helm是helm的客户端部分 tiller是helm的服务器端部分 报错 报错Error: incompatible versions client[v2.14.1] server[v2.13.0] ...

  5. 如何理解AWS 网络,如何创建一个多层安全网络架构

    目录 一.要求 网络架构图 网络各组件关系 二.操作步骤 2.1.网络设置 2.2.安全设置 2.3.创建实例 三.费用 3.1.NAT 网关费用 一.要求 创建一个三层网络架构,服务器只能通过跳板机 ...

  6. 用一两句话说一下你对“盒模型”这个概念的理解,和它都涉及到哪些css属性

    网页设计中常听的属性名:内容(content).填充(padding).边框(border).边界(margin), CSS盒子模式都具备这些属性. 这些属性我们可以用日常生活中的常见事物——盒子作一 ...

  7. javascript好文 --- 深入理解可视区尺寸client

    可视区大小 可视区大小client又称为可见大小或客户区大小,指的是元素内容及其内边距所占据的空间大小 clientHeight clientHeight属性返回元素节点的可见高度 clientHei ...

  8. 如何理解“Unix 里一切都是文件”这句话-在 UNIX 中,一切都是字节流

    UNIX 操作系统的设计.用户界面.文化和演变都是建立在它的一套统一的想法和概念上.其中最重要的一点可能是“一切皆文件”,而这个概念被认为是 UNIX 的灵魂之一. 这一关键设计原则提供了一个统一的范 ...

  9. 深刻的理解Fragment生命周期 都在做什么,fragment生命周期

    先上一个生命周期的图片吧  下面挨个的说一下我平时 都怎么使用 这些 回调函数的 流程: onAttach() 作用:fragment已经关联到activity, 这个是 回调函数 @Override ...

随机推荐

  1. JSP页面包含其他页面的三种方式及区别

    一. <%@ include file="header.inc"%> 该指令在编译之前先读入指定的页面中的内容(并不对动态内容求值),融合后的完整页面再被整体的转换为一 ...

  2. linux c 的main 函数中的return 和 查看返回参数 argv 与 argc 作用

    hello.c #include <stdio.h> int main(int argv, char* argc[]) { printf("hello word!\n" ...

  3. odoo ERP 系统安装与使用

    https://hub.docker.com/_/odoo/ #!/bin/bash sudo docker pull postgres:10sudo docker pull odoo:11.0 su ...

  4. MyBatis中批量insert

    在orcale和mybatis执行批量插入是不一样的. orcale如下:(这里要注意的是:useGeneratedKeys="false" ) 方式1:oracle批量插入使用 ...

  5. C++中vecotr表示二维数组并自己实现一个Grid类

    1 C++中使用vector来表示二维数组 声明一个二维数组: vector<vector<int>> dp(row, vector<int>(col)); 将变量 ...

  6. Vue Vue项目目录结构梳理

    Vue项目目录结构梳理   by:授客 QQ:1033553122 1.   结构梳理   . ├── build/                      # webpack 配置文件: │   ...

  7. linux运维、架构之路-Kubernetes本地镜像仓库+dashboard部署

    一.部署docker registry            生产环境中我们一般通过搭建本地的私有镜像仓库(docker registry)来拉取镜像. 1.拉取registry镜像 [root@k8 ...

  8. MCU2FPGA之SPI时序总线

    转载自:http://blog.csdn.net/ce123/article/details/6895408 SPI总线有四种工作方式(SP0, SP1, SP2, SP3),其中使用的最为广泛的是S ...

  9. [洛谷2257]ZAP-Queries 题解

    前言 这道题还是比较简单的 解法 首先将题目转化为数学语言. 题目要我们求的是: \[\sum_{i=1}^a\sum_{j=1}^b[gcd(i,j)=d]\] 按照套路1,我们将其同时除以d转换为 ...

  10. HDU 6623 Minimal Power of Prime

    Time limit 1000 ms Memory limit 65536 kB OS Windows 中文题意 给一个数n,设将n质因数分解后可以得到 \[n=\prod_{i=1}^{\omega ...