android分析之Binder 02
分析Java层的ServiceManager,看看Binder在Java层是如何实现的。
public final class ServiceManager {
    private static final String TAG = "ServiceManager";
    private static IServiceManager sServiceManager;//IserviceManager是一个接口,定义了通用(公共)方法。
    private static HashMap<String, IBinder> sCache = new HashMap<String, IBinder>();//缓存,其值是IBinder
...
    public static IBinder getService(String name) {
        try {
            IBinder service = sCache.get(name);//先从缓存中查找
            if (service != null) {
                return service;
            } else {
                return getIServiceManager().getService(name);//生成新的IBinder
            }
        } catch (RemoteException e) {
            Log.e(TAG, "error in getService", e);
        }
        return null;
    }
...
这里的ServiceManager仅仅是一种封装,其成员变量和方法都是static。从上面的sCache保存的键值对和getService的返回值类型为IBinder(与C++层的IBinder不同)可以看出,通过ServiceManager得到的是一个IBinder类型对象,通过后面的分析,实际可以看出它是BpBinder对象。
    private static IServiceManager getIServiceManager() {
        if (sServiceManager != null) {
            return sServiceManager;
        }
        // Find the service manager
        sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());//找到IServiceManager对象,并返回
        return sServiceManager;
    }
...
    /**
     * 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();//BinderInternale:调用native函数,返回IBinder对象
...
    static public IServiceManager asInterface(IBinder obj)//传入的就是上面的那个IBinder对象,记住这是Java对象
    {
        if (obj == null) {
            return null;
        }
        IServiceManager in =
            (IServiceManager)obj.queryLocalInterface(descriptor);//从IBinder对象里查找,并转换为IServiceManager对象
        if (in != null) {
            return in;
        }
        return new ServiceManagerProxy(obj);//如果找不到,则使用传入的IBinder对象生成一个ServiceManagePorxy对象
    }
上面绕了一圈,直接从ServiceManagerProxy来看,有两方面:1,得到native层的一个某对象,并转换为IBinder,即上面的native IBinder getContextObject();2,使用获得的IBinder来生成一个ServiceManagerProxy对象。下面来看看ServiceManagerProxy的构造方法:
    public ServiceManagerProxy(IBinder remote) {
        mRemote = remote;//mRemote是IBinder类型,这里将传入的IBinder对象保存在mRemote
    }
    public IBinder getService(String name) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IServiceManager.descriptor);
        data.writeString(name);
        mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);//最后使用IBinder的transact来传送数据
        IBinder binder = reply.readStrongBinder();
        reply.recycle();
        data.recycle();
        return binder;
    }
小结:调用ServiceManager的getService(),会生成一个ServiceManagerProxy对象,该对象持有一个mRemote(IBinder),通过该mRemote(它是BpBinder在Java层的代表)可以向下层发送数据。
getContextObject分析:
public static final native IBinder getContextObject();//BinderInternale:调用native函数,返回IBinder对象——对应为下面这个函数:
static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
sp<IBinder> b = ProcessState::self()->getContextObject(NULL);//走到这里:b为一个BpBinder
return javaObjectForIBinder(env, b);//返回一个Java层的BinderProxy
到这里明白了,上面的mRemote持有的就是BinderProxy对象。而上面调用mRemote对象的transact()方法就是调用BinderProxy的transact方法:
public native boolean transact(int code, Parcel data, Parcel reply,
int flags) throws RemoteException;
...
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);
if (data == NULL) {
return JNI_FALSE;
}
Parcel* reply = parcelForJavaObject(env, replyObj);
if (reply == NULL && replyObj != NULL) {
return JNI_FALSE;
} IBinder* target = (IBinder*)//将BinderProxy转换为BpBinder
env->GetIntField(obj, gBinderProxyOffsets.mObject);
...
status_t err = target->transact(code, *data, reply, flags);//调用BpBinder来与更下层通信
...
走到这里:Java层主要就是获取Native层的BpBinder,并使用它来与下层通信。
android分析之Binder 02的更多相关文章
- android分析之Binder 01
		终于还是得写一篇关于Binder的文章了.从最初接触Android到花大把时间研究Android源码,Binder一直是分析道路的拦路虎.看了几本最流行的Android源码分析书籍,每次基本上都不能把 ... 
- Android系统进程间通信Binder机制在应用程序框架层的Java接口源代码分析
		文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6642463 在前面几篇文章中,我们详细介绍了A ... 
- 098 01 Android 零基础入门  02 Java面向对象 03 综合案例(学生信息管理) 02 案例分析及实现 02 编写并测试Subject类
		098 01 Android 零基础入门 02 Java面向对象 03 综合案例(学生信息管理) 02 案例分析及实现 02 编写并测试Subject类 本文知识点:编写并测试Subject类 说明: ... 
- 099 01 Android 零基础入门  02 Java面向对象 03 综合案例(学生信息管理) 02 案例分析及实现 03 编写并测试Student类
		099 01 Android 零基础入门 02 Java面向对象 03 综合案例(学生信息管理) 02 案例分析及实现 03 编写并测试Student类 本文知识点:编写并测试Subject类 说明: ... 
- 101 01 Android 零基础入门  02 Java面向对象 03 综合案例(学生信息管理) 02 案例分析及实现 05 通过方法实现学生类与专业类关联——方案二
		101 01 Android 零基础入门 02 Java面向对象 03 综合案例(学生信息管理) 02 案例分析及实现 05 通过方法实现学生类与专业类关联--方案二 本文知识点:通过方法实现学生类与 ... 
- Android深入浅出之Binder机制(转)
		Android深入浅出之Binder机制 一 说明 Android系统最常见也是初学者最难搞明白的就是Binder了,很多很多的Service就是通过Binder机制来和客户端通讯交互的.所以搞明白B ... 
- Android IPC机制—Binder的工作机制
		进程和线程的关系 IPC机制即为跨进程通信,是inter-Process Communication的缩写.是指两个进程之间进行通信.在说进程通信之前,我们的弄明白什么是线程,什么是进程.进程和线程是 ... 
- 从AIDL开始谈Android进程间Binder通信机制
		转自: http://tech.cnnetsec.com/585.html 本文首先概述了Android的进程间通信的Binder机制,然后结合一个AIDL的例子,对Binder机制进行了解析. 概述 ... 
- [Android进阶]Binder学习(初始篇)
		Android中Binder学习(初始篇) 本篇博客学习自侯亮的博客.地址为: 红茶一杯话Binder 1 什么是Binder? 简单地说.Binder是Android平台上的一种跨进程交互技术. 该 ... 
随机推荐
- MySQL 基础面试题
			请写出什么是事务? 事务是一组不可分割的 DML 语句,事务处理可以用来维护数据库的完整性,保证一组 SQL 语句要么全部执行成功,要么全部不执行,只有 InnoDB 存储引擎才支持事务 . 事务的特 ... 
- 微服务架构Day02-SpringBoot日志slf4j
			日志框架 日志门面(接口,日志抽象层 ) 日志实现 JCL(Jakarta Commons Logging).slf4j(Simple Logging Facade for Java).jboss-l ... 
- 牛客多校第八场E Explorer(左开右闭线段树+可撤回并查集)题解
			题意: 传送门 有\(n\)个点构成一个无向图,每条边有\(L_i,R_i\)表示这条边只能允许编号为\(L_i\dots R_i\)的人通过,现在问你最多有几个人能从\(1\)走到\(n\). 思路 ... 
- Dapr 正式发布1.0
			年前我写了一篇博客<Dapr 已在塔架就位 将发射新一代微服务>, 今天Dapr 正式发布了1.0 : Dapr Runtime v1.0.0 Dapr dotnet SDK v1.0.0 ... 
- codepen 上25个最受欢迎的HTML/CSS代码
			Codepen是一个非常了不起的网站,优设哥在设计师网址导航上也大力推荐过,得到了很多同学的喜爱,也是全球web前端开发人员的圣地! 我搜索了一些时下最好最流行的codepen(仅限于HTML和CSS ... 
- ES2015 (ES6) 新特性: 20 个
			ES2015 (ES6) 新特性 http://babeljs.io/docs/learn-es2015/ Learn ES2015 A detailed overview of ECMAScript ... 
- VSCode & SQL
			VSCode & SQL MySQL MySQL https://marketplace.visualstudio.com/items?itemName=formulahendry.vscod ... 
- koa response image
			koa response image koa.js v1.x generator *function v2.x Async/Await koajs/examples https://github.co ... 
- express+apollo+mongodb
			阿波罗服务器入门 λ yarn add --dev @babel/core @babel/cli @babel/preset-env λ yarn add --dev nodemon // " ... 
- ubuntu无法连接有线网
			问题描述: ubuntu下仅能连接无线网,不能连接有线网,在有线网的下面是没有选项可供连接. 解决方法: 编辑 /etc/network/interfaces 这个文件 将里面仅仅写两句话 auto ... 
