美文网首页
Java层 Binder笔记相关(一)

Java层 Binder笔记相关(一)

作者: leenpong | 来源:发表于2019-03-02 18:38 被阅读0次

    前言:

    1.Binder是什么?
    2.Binder的原理是什么?
    3.Binder如何实现?

    1.Binder是什么?

    Binder是Anroid平台跨进程通信的一种重要的实现方式(
    另外三种:

    • Messenger
    • broadcast
    • socket

    ),是Google基于OpenBinder实现的进程间通信的驱动程序框架, 由于Android是每个应用或者服务(AMS,IMS)都运行在一个独立的进程,每个进程之间的数据是独立的,想要通信就需要一种跨进程的技术.

    2.Binder的原理是什么?

    2.2 Binder对应的驱动设备文件为:/dev/binder.

    • 2.2.1通过Client/Service模式 : C/S之间维护一个线程池进程通信,通过dev/binder该设备文件调用内核中的bingder驱动程序

    2.2.1.1.Client组件对应的是BnInterface,描述本地binder对象,service组件对应的是BpInterface。描述本地binder代理对象.
    2.2.1.2系统定义了IBinder接口,其中Binder和BinderProxy分别实现了IBinder接口,前者代表服务端Bn,而后者代表客户端Bp.

    • 2.2.2 Binder进行进程间通信: 首先要调用open函数打开设备文件dev/binder获得文件描述符,再调用mmp将该描述符映射到内核地址空间,然后分配内核缓冲区,该缓冲区是用来传递数据的,才能通过这个和binder驱动程序交互。

    2.3 .
    Android应用层系统想启动另外一个进程里面的service或者activity等组件,最终都是通过一个远程的mRemote Binder对象去跨进程通信想AMS发送一个请求启动,下面通过分析AMS来分析Binder的原理。

    其中AMS的继承方式:

    ActivityManagerService ->ActivityManagerService->Binder

        public ActivityManagerNative() {
            attachInterface(this, descriptor);
        }
    
        /**
         * Convenience method for associating a specific interface with the Binder.
         * After calling, queryLocalInterface() will be implemented for you
         * to return the given owner IInterface when the corresponding
         * descriptor is requested.
         */
        public void attachInterface(IInterface owner, String descriptor) {
            mOwner = owner;
            mDescriptor = descriptor;
        }
          //from IActivityManager
        String descriptor = "android.app.IActivityManager";
    
    

    当启动一个Activity的流程为:

    Activity.java:
    public void startActivityForResult(Intent intent, int requestCode,@Nullable Bundle options) {
            if (mParent == null) {
                Instrumentation.ActivityResult ar =
                    mInstrumentation.execStartActivity(
                        this, mMainThread.getApplicationThread(), mToken, this,
                        intent, requestCode, options);
            }
    
    
    
    Instrumentation.java:
    public void execStartActivitiesAsUser() {
    
    int result = ActivityManagerNative.getDefault()
                    .startActivities(whoThread, who.getBasePackageName(), intents, resolvedTypes,
                            token, options, userId);
    
    }
    
    ActivityManagerNative.java:
        /**
         * Retrieve the system's default/global activity manager.
         */
        static public IActivityManager getDefault() {
            return gDefault.get();
        }
    
    //
        private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
            protected IActivityManager create() {
                            //拿到对应的ServiceManaerService
                             IBinder b = ServiceManager.getService("activity");
                            if (false) {
                                Log.v("ActivityManager", "default service binder = " + b);
                            }
                            IActivityManager am = asInterface(b);
                            if (false) {
                                Log.v("ActivityManager", "default service = " + am);
                            }
                            return am;
                    }
                    。
                    。
                    。
            }
    }
    
    其中gDefault最终拿到的是一个面向底层的客户端BinderProxy对象(ActivityManagerProxy)
    

    从上面代码可以看出最终是调用AMN的startActivity方法。
    但是该Binder客户端对象就是是跟底层那个目标通信呢?

    ServiceManager.getService("activity");
    
        /**
         * Returns a reference to a service with the given name.
         * 
         * @param name the name of the service to get
         * @return a reference to the service, or <code>null</code> if the service doesn't exist
         */
        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;
        }
    
        private static IServiceManager getIServiceManager() {
            if (sServiceManager != null) {
                return sServiceManager;
            }
    
            // Find the service manager
            sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
            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();
    
    

    从上面可以知道getContextObject返回了一个指向地城ServiceManager的Native BinderProxy对象,并且在JAVA层封装 起来给JAVA调用,如下:

        /**
         * Cast a Binder object into a service manager interface, generating
         * a proxy if needed.
         */
    //其中obj就是上面传进来指向Native BinderProxy对象的地址。
        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);
        }
    

    上面ServiceManagerProxy对象就是封装了在BinderInternal拿到的Native对象的。

    下面通过分析getService方法,分析客户端发送请求过程:

        
        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 binder = reply.readStrongBinder();
            reply.recycle();
            data.recycle();
            return binder;
        }
      //其中mRemote就是BinderInternal. getContextObjectd的navtive对象。
    也就是说,将数据封装成Parcel对象,然后通过native binder发起请求。
    
    

    上面是客户端的请求。

    ActivityManagerService.java:

    @Override
        public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
                throws RemoteException {
            switch (code) {
            case START_ACTIVITY_TRANSACTION:
            {
                data.enforceInterface(IActivityManager.descriptor);
                IBinder b = data.readStrongBinder();
                IApplicationThread app = ApplicationThreadNative.asInterface(b);
                String callingPackage = data.readString();
                Intent intent = Intent.CREATOR.createFromParcel(data);
                String resolvedType = data.readString();
                IBinder resultTo = data.readStrongBinder();
                String resultWho = data.readString();
                int requestCode = data.readInt();
                int startFlags = data.readInt();
                ProfilerInfo profilerInfo = data.readInt() != 0
                        ? ProfilerInfo.CREATOR.createFromParcel(data) : null;
                Bundle options = data.readInt() != 0
                        ? Bundle.CREATOR.createFromParcel(data) : null;
                int result = startActivity(app, callingPackage, intent, resolvedType,
                        resultTo, resultWho, requestCode, startFlags, profilerInfo, options);
                reply.writeNoException();
                reply.writeInt(result);
                return true;
            }
    
    

    上面是AMS实现的接受到客户端请求的实现方法。
    我们知道AMS是继承Binder,当底层收到请求是,最终会调用Binder.java对应的方法:

    
        // Entry point from android_util_Binder.cpp's onTransact
        private boolean execTransact(int code, long dataObj, long 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;
            // Log any exceptions as warnings, don't silently suppress them.
            // If the call was FLAG_ONEWAY then these exceptions disappear into the ether.
            try {
                res = onTransact(code, data, reply, flags);
    }
    
    

    其中onTransact是一个抽象方法,其中AMS上面实现了该方法,完成请求。
    流程如图:


    image.png

    后记:JAVA中搭建了一整套框架,如IBinder接口,Binder类,和BiindeProxy(如ServiceManagerProxy)其中本质就是向binder驱动发送请求或者接受回复。
    即使不使用JAVA的框架,也是可以实现,比如ServiceManager作为Binder的一个核心程序,就是直接读取/dev/binder设备。

    相关文章

      网友评论

          本文标题:Java层 Binder笔记相关(一)

          本文链接:https://www.haomeiwen.com/subject/mrfyuqtx.html