Skip to content

android binder

cheyiliu edited this page Sep 30, 2014 · 18 revisions

binder

binder on java side

先来个类比:
A想联系B,于是他拿出手机拨号,电话公司获得A的请求并呼叫B的号码,B听到铃声并接通,电话公司通知A呼叫已经接通,A开始和B沟通。

工程狮翻译:
client想和service沟通,于是client拿出bindService来拨号,framework(具体是谁还没看代码TODO)获得client的请求并呼叫service,service收到onBind的铃声并接通(返回binder),framework通过onServiceConnected通知client已经接通,client和service开始通话。

call sequence

bindService, request to bind the target the service
onBind, return the instance of IXXService.Stub which extends from IBinder
onServiceConnected(ComponentName name, IBinder service), got an IBinder and to get the proxy by IXXService.Stub.asInterface(service)

注: call sequence中onServiceConnected得到的ibinder和IXXService.Stub.asInterface(service)的返回值和client/service是否是同一进程有关联。

class hierarchy

class diagram of java side

demo code

public interface IXXService extends android.os.IInterface{
   // API define
   public void API1(java.lang.String arg1, java.lang.String arg2, java.lang.String arg3)
            throws android.os.RemoteException;
}
public static abstract class IXXService.Stub extends android.os.Binder implements IXXService{
        private static final java.lang.String DESCRIPTOR = "your.package.IXXService";

        /** Construct the stub at attach it to the interface. */
        public Stub()
        {
            this.attachInterface(this, DESCRIPTOR);
        }

        /**
         * Cast an IBinder object into an
         * your.package.IXXService
         * interface, generating a proxy if needed.
         */
        public static your.package.IXXService asInterface(
                android.os.IBinder obj)
        {
            if ((obj == null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof your.package.IXXService))) {
                return ((your.package.IXXService) iin);
            }
            return new your.package.IXXService.Stub.Proxy(
                    obj);
        }

        @Override
        public android.os.IBinder asBinder()
        {
            return this;
        }

        @Override
        public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply,
                int flags) throws android.os.RemoteException
        {
            switch (code)
            {
                case INTERFACE_TRANSACTION: {
                    reply.writeString(DESCRIPTOR);
                    return true;
                }
                case TRANSACTION_API1: {
                    data.enforceInterface(DESCRIPTOR);
                    java.lang.String _arg0;
                    _arg0 = data.readString();
                    java.lang.String _arg1;
                    _arg1 = data.readString();
                    java.lang.String _arg2;
                    _arg2 = data.readString();
                    this.API1(_arg0, _arg1, _arg2);
                    reply.writeNoException();
                    return true;
                }
               
            }
            return super.onTransact(code, data, reply, flags);
        }


        static final int TRANSACTION_API1 = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);

    }
 private static class IXXService.Stub.Proxy implements IXXService
        {
            private android.os.IBinder mRemote;

            Proxy(android.os.IBinder remote)
            {
                mRemote = remote;
            }

            @Override
            public android.os.IBinder asBinder()
            {
                return mRemote;
            }

            public java.lang.String getInterfaceDescriptor()
            {
                return DESCRIPTOR;
            }

            @Override
            public void API1(java.lang.String arg1, java.lang.String arg2,
                    java.lang.String arg3) throws android.os.RemoteException
            {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    _data.writeString(arg1);
                    _data.writeString(arg2);
                    _data.writeString(arg3);
                    mRemote.transact(Stub.TRANSACTION_API1, _data, _reply, 0);
                    _reply.readException();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }

        }

binder on native side

  • class hierarchy binder_native_side.jpg
  • call sequence
    1. define API class IDemo: public IInterface
    2. impl class BpDemo: public BpInterface , remote()->transact(PUSH, data, &reply);
    3. impl class BnDemo: public BnInterface , onTransact(){ ... }
    4. register the service, defaultServiceManager()->addService(String16("Demo"), new Demo());
    5. client get sm->getService(String16("Demo"));
    6. call

demo:

https://github.com/cheyiliu/testBinder
https://github.com/cheyiliu/BinderDemo

ref:

http://blog.csdn.net/luoshengyang/article/details/6618363
https://thenewcircle.com/s/post/1340/Deep_Dive_Into_Binder_Presentation.htm#title-slide
http://www.cnblogs.com/samchen2009/p/3316001.html

question?

why proxy has a binder VS the stub extends from the binder?

todo

  • java 层bindService是如何管理的
  • native srviceManager是如何管理的
  • binder 驱动
Clone this wiki locally