Android Binder通信学习

Android Binder通信学习。

以Hello为例说明设计的几个概念关系:

IhelloService.h : 提供给应用程序使用的类接口,注意是说明服务能够提供的哪些操作接口。

【注意】实际不只是定义一个接口类,还继承该接口并添加虚接口onTransact后定义了一个抽象类BnHelloService

class IHelloService: public IInterface
        {
        public:
            DECLARE_META_INTERFACE(HelloService);   /* 此宏声明了接口IHelloService::getInterfaceDescriptor 和 IHelloService::asInterface(这个接口可以生成一个Bp实例) */
            virtual void sayhello(void) = 0;
            virtual int sayhello_to(const char *name) = 0;
        };

        class BnHelloService: public BnInterface<IHelloService>
        {
        public:
            virtual status_t    onTransact( uint32_t code,
                                            const Parcel& data,
                                            Parcel* reply,
                                            uint32_t flags = 0);

            virtual void sayhello(void);
            virtual int sayhello_to(const char *name);

        };

BnHelloService.cpp : 为了之后可以用BnHelloService实例化对象,需要对BnHelloService完成接口中定义的虚函数.【这个是实际去干活的服务,’别人‘只是给他发需求】

        status_t BnHelloService::onTransact( uint32_t code,
                                    const Parcel& data,
                                    Parcel* reply,
                                    uint32_t flags)
        {


            switch (code) {
                case HELLO_SVR_CMD_SAYHELLO: 
                    sayhello();
                    break;
                case HELLO_SVR_CMD_SAYHELLO_TO: 
                    sayhello_to(name8.string());
                     break;
            }
            return NO_ERROR;
        }
        void BnHelloService::sayhello(void)
        {
            static int cnt = 0;
            ALOGI("say hello : %d\n", ++cnt);

        }
        int BnHelloService::sayhello_to(const char *name)
        {
            static int cnt = 0;
            ALOGI("say hello to %s : %d\n", name, ++cnt);
            return cnt;
        }

BpHelloService.cpp : 继承抽象的接口类,并去实现虚函数,这样才能实例化对象,成为给服务发需求的‘别人’。【BpXXService负责给服务发需求,这么说服务并不是谁叫我干活就干,我只听Bp的】

        class BpHelloService: public BpInterface<IHelloService>
        {
        public:
            BpHelloService(const sp<IBinder>& impl)
                : BpInterface<IHelloService>(impl)
            {
            }

            void sayhello(void)
            {
                Parcel data, reply;
                data.writeInt32(0);
                data.writeString16(String16("IHelloService"));

                remote()->transact(HELLO_SVR_CMD_SAYHELLO, data, &reply);
            }

            int sayhello_to(const char *name)
            {
                Parcel data, reply;
                int exception;

                data.writeInt32(0);
                data.writeString16(String16("IHelloService"));

                data.writeString16(String16(name));

                remote()->transact(HELLO_SVR_CMD_SAYHELLO_TO, data, &reply);

                exception = reply.readInt32();
                if (exception)
                    return -1;
                else
                    return reply.readInt32();
                }

        };
        IMPLEMENT_META_INTERFACE(HelloService, "android.media.IHelloService");/* 此宏具体实现了接口IHelloService::getInterfaceDescriptor 和 IHelloService::asInterface */

HelloServer.c : 实现的最底层接收请求的服务器,提供怎样的服务呢?只提供这个里面提供的服务BnHelloService!

        int main(void)
        {
            /* 打开biner并mmap进内存 */
            sp<ProcessState> proc(ProcessState::self());

            /* 获得 BnServiceManager */
            sp<IServiceManager> sm = defaultServiceManager();

            /* 添加服务 */
            sm->addService(String16("hello"), new BnHelloService());

            /* 循环体,不断获取服务并处理 */
            ProcessState::self()->startThreadPool();
            IPCThreadState::self()->joinThreadPool();

            return 0;
        }

HelloClient.c : 最底层发请求的客户端,这才是满肚子需求的底层人民啊。

        int main(int argc, char **argv)
        {
            int cnt;

            /* 打开biner并mmap进内存 */
            sp<ProcessState> proc(ProcessState::self());

            /* 获得 BpServiceManager */
            sp<IServiceManager> sm = defaultServiceManager();

            /* 获得 根据hello名字 获取服务  */
            sp<IBinder> binder =
                sm->getService(String16("hello"));

            if (binder == 0)
            {
                ALOGI("can't get hello service\n");
                return -1;
            }

        /* Service肯定是 BpHelloService 指针??
        * interface_cast<IHelloService>(binder)  ->            IHelloService::asInterface(binder);(IMPLEMENT_META_INTERFACE宏中定义)
            *【结果:在下面代码中分配一个BpHelloService实例指针】 
            */
            sp<IHelloService> service =
                interface_cast<IHelloService>(binder);

            /* 调用 BpHelloService提供的函数  */

            service->sayhello();
            ALOGI("client call sayhello");


            return 0;
        }

好了,下面来总结下:背景是世界的阶级斗争依然是如此的激烈,因此不管干啥我们都分等级,Binder服务也是如此,有需求只向上级反映,由上级出处理:

                BpServiceManager <- HelloClient
                     |
                    \ /
                BnServiceManager -> HelloServer


Binder的java实现。

IHelloService.aidl : Android接口描述文件,只要用户定义自己需要提供的接口,然后放到frameworks/base/core/java/android/os下,并修改

                        frameworks/base/Android.mk  添加一行
                        core/java/android/os/IHelloService.aidl\
代码:
/** {@hide} */
interface IHelloService
{
    void sayhello();
    int sayhello_to(String name);
}

IHelloService.java : 由aidl文件编译出来的接口类,里面除了用户自定义的接口外还包含一个 stub 的内部类。

【stub】:为屏蔽客户调用远程主机上的对象,必须提供某种方式来模拟本地对象,这种本地对象称为存根(stub),根负责接收本地方法调用,并将它们委派给各自的具体实现对象
代码只保留框架:
public interface IHelloService extends android.os.IInterface
{
    /** Local-side IPC implementation stub class. */
    public static abstract class Stub extends android.os.Binder implements IHelloService
    {
        private static final java.lang.String DESCRIPTOR = "IHelloService";
        /** Construct the stub at attach it to the interface. */
        public Stub()
        {
            this.attachInterface(this, DESCRIPTOR);
        }
        /**
         * Cast an IBinder object into an IHelloService interface,
         * generating a proxy if needed.
         */
        public static IHelloService asInterface(android.os.IBinder obj)
        {

            return new IGoodbyeService.Stub.Proxy(obj);  /* 客户端获取服务后,需要转化为proxy才能进行最终的接口调用  */
        }

        @Override public android.os.IBinder asBinder()
        {
            return this;
        }
        /* 实际处理需求的服务端,类似于C++ binder中的BnXxService功能,用于接收需求并实际出执行需求任务 */
        @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_saygoodbye:
                {
                    data.enforceInterface(DESCRIPTOR);
                    this.saygoodbye();                      /* 调用本stub中定义的接口函数 */
                    reply.writeNoException();
                    return true;
                }
                case TRANSACTION_saygoodbye_to:
                {
                    data.enforceInterface(DESCRIPTOR);
                    java.lang.String _arg0;
                    _arg0 = data.readString();
                    int _result = this.saygoodbye_to(_arg0);  /* 调用本stub中定义的接口函数 */
                    reply.writeNoException();
                    reply.writeInt(_result);
                    return true;
                }
            }
        }
        private static class Proxy implements IGoodbyeService  /* 代理类,类似于C++ binder中的BpXxService,用于接收需求并封装数据发生需求给服务端 */
        {
          mRemote.transact(Stub.TRANSACTION_saygoodbye_to, _data, _reply, 0);
        }

    }

    public void sayhello() throws android.os.RemoteException;
    public int sayhello_to(java.lang.String name) throws android.os.RemoteException;
}

Helloservice.java : 服务器代码,非常简单,继承IHelloService.Stub的接口,并实现最终干活的代码。

public class HelloService extends IHelloService.Stub {
    private static final String TAG = "HelloService";
    private int cnt1 = 0;
    private int cnt2 = 0;

    public void sayhello() throws android.os.RemoteException {
        cnt1++;
        Slog.i(TAG, "sayhello : cnt = "+cnt1);
    }

    public int sayhello_to(java.lang.String name) throws android.os.RemoteException {
        cnt2++;
        Slog.i(TAG, "sayhello_to "+name+" : cnt = "+cnt2);
        return cnt2;
    }
}

TestServer.java : 用户这边提供服务的代码,目的就是注册一个服务

public class TestServer {
    private static final String TAG = "TestServer";

    public static void main(String args[])
    {
        /* add Service */
        Slog.i(TAG, "add hello service");
        ServiceManager.addService("hello", new HelloService()); /* 此处添加负责服务器任务的类 */

        while (true)
        {
            try {
                Thread.sleep(100);
            } catch (Exception e){}
        }

    }
}

TestClient.java : 最底层发需求的用户代码。

public class TestClient {
    private static final String TAG = "TestClient";

    public static void main(String args[])
    {
        /* 1. getService */
        IBinder binder = ServiceManager.getService("hello");
        if (binder == null)
        {
            System.out.println("can not get hello service");
            Slog.i(TAG, "can not get hello service");
            return;
        }

        IHelloService svr = IHelloService.Stub.asInterface(binder); /* 得到接口的代理 */

        if (args.length == 1)
        {
                try {
                svr.sayhello();
                System.out.println("call sayhello");
                Slog.i(TAG, "call sayhello");
            } catch (Exception e) {}
        }
        else
        {
                try {
                int cnt = svr.sayhello_to(args[1]);
                System.out.println("call sayhello_to "+args[1]+" : cnt = "+cnt);
                Slog.i(TAG, "call sayhello_to "+args[1]+" : cnt = "+cnt);
            } catch (Exception e) {
                    System.out.println("call sayhello_to , err :"+e);
                    Slog.i(TAG, "call sayhello_to , err : "+e);
            }
        }

    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值