Binder 机制和 AIDL Demo

概述

AidlDemo 项目参考
该 Github 项目有两个独立的项目,
一个是 AidlClient,代表客户端;
另一个是 AidlServer,代表服务端。

aidl 使用的三步曲:

  • client,server 端都是采用相同的 aidl
  • server 端,new 一个 Stub 实例,并实现 aidl 中定义的函数,然后在 onBind 函数中返回 IBinder 类型的该 Stub 实例。
  • client 端,实现发起绑定逻辑,并在绑定完成的回调中拿到 IBinder 类型的参数,并通过 Stub.asInterfac 函数转变为代理类实例,用 aidl 接口依赖。

下面以 AidlDemo 项目参考 为例进行分析。

两端都用同一个 Aidl

Client 端的 aidl 路径:
/AidlDemo/AidlClient/app/src/main/aidl/com/guohao/aidl/server/IBookManager.aidl

Server 端的 aidl 路径:
/AidlDemo/AidlServer/app/src/main/aidl/com/guohao/aidl/server/IBookManager.aidl

aidl 源码:

// IBookManager.aidl

package com.guohao.aidl.server;
interface IBookManager {

    int add(int num1,int num2);

    int wrong_add(int num1,int num2);

    int more_fun();
}

定义好的 aidl 接口,编译后会生成 java 文件:{工程根目录}/app/build/generated/source/aidl/debug/com/guohao/aidl/server/IBookManager.java

源码如下:
有点长,先看 IBookManager.java 接口的结构:

  • add 接口函数
  • wrong_add 接口函数
  • more_fun 接口函数
  • Stub 类
    • asBinder 函数
    • asInterface 函数,client 使用,把 server 的 IBinder 转成 Proxy
    • onTransact 函数,server 使用,接收 client 通信的回调
    • Proxy 类,client 使用
      • asBinder 函数
      • add 函数,向 Binder 驱动发送通信,继而转到 server 的 onTransact 函数
      • wrong_add 函数,同上
      • more_fun 函数,同上

具体源码:

// IBookManager.java

/*
 * This file is auto-generated.  DO NOT MODIFY.
 * Original file: /Users/guohao/AS_Proj/AidlDemo/AidlServer/app/src/main/aidl/com/guohao/aidl/server/IBookManager.aidl
 */
package com.guohao.aidl.server;

public interface IBookManager extends android.os.IInterface {
    /**
     * Local-side IPC implementation stub class.
     */
    public static abstract class Stub extends android.os.Binder implements com.guohao.aidl.server.IBookManager {
    
        // 用于告诉 Binder 驱动,向哪个进程发起通信
        private static final java.lang.String DESCRIPTOR = "com.guohao.aidl.server.IBookManager";

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

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

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

        // 在 server 端被调用,接收 client 通信的回调
        @Override
        public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
            java.lang.String descriptor = DESCRIPTOR;
            switch (code) {
                case INTERFACE_TRANSACTION: {
                    reply.writeString(descriptor);
                    return true;
                }
                case TRANSACTION_add: {
                    data.enforceInterface(descriptor);
                    int _arg0;
                    _arg0 = data.readInt();
                    int _arg1;
                    _arg1 = data.readInt();
                    int _result = this.add(_arg0, _arg1);
                    reply.writeNoException();
                    reply.writeInt(_result);
                    return true;
                }
                case TRANSACTION_wrong_add: {
                    ...
                    int _result = this.wrong_add(_arg0, _arg1);
                    ...
                    return true;
                }
                case TRANSACTION_more_fun: {
                    data.enforceInterface(descriptor);
                    int _result = this.more_fun();
                    ...
                    return true;
                }
                default: {
                    return super.onTransact(code, data, reply, flags);
                }
            }
        }

        // 在 client 端持有实例,通过 mRemote.transact 函数向 Binder 驱动发起跨进程通信
        private static class Proxy implements com.guohao.aidl.server.IBookManager {
            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 int add(int num1, int num2) throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                int _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    _data.writeInt(num1);
                    _data.writeInt(num2);
                    mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.readInt();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }

            @Override
            public int wrong_add(int num1, int num2) throws android.os.RemoteException {
                ...
                try {
                    ...
                    mRemote.transact(Stub.TRANSACTION_wrong_add, _data, _reply, 0);
                    ...
                } finally {
                    ...
                }
                return _result;
            }

            @Override
            public int more_fun() throws android.os.RemoteException {
                ...
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    mRemote.transact(Stub.TRANSACTION_more_fun, _data, _reply, 0);
                    ...
                } finally {
                    ...
                }
                return _result;
            }
        }

        // mRemote.transact 函数时会使用的标志位,用于识别调用哪个函数
        static final int TRANSACTION_add = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
        static final int TRANSACTION_wrong_add = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
        static final int TRANSACTION_more_fun = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
    }

    public int add(int num1, int num2) throws android.os.RemoteException;

    public int wrong_add(int num1, int num2) throws android.os.RemoteException;

    public int more_fun() throws android.os.RemoteException;
}

server端的实现

server 端的工作:

new 一个 Stub 实例,并实现 aidl 中定义的函数,然后在 onBind 函数中返回 IBinder 类型的该 Stub 实例

源码:

// AidlService.java

public class AidlService extends Service {
    public AidlService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        
        // 返回接口 IBookManager.Stub 实例
        return aidlServer;
    }

    // 声明并实现 IBookManager 接口的 stub 类实例
    IBookManager.Stub aidlServer = new IBookManager.Stub(){

        @Override
        public int add(int num1, int num2) throws RemoteException {
            Log.d("guohao","add...num1 = " + num1 + " ,num2 = " + num2 );
            return ( num1 + num2 );
        }

        @Override
        public int wrong_add(int num1, int num2) throws RemoteException {
            Log.d("guohao","wrong_add...num1 = " + num1 + " ,num2 = " + num2 );
            return ( num1 + num2 );
        }

        @Override
        public int more_fun() throws RemoteException {
            Log.d("guohao","more_fun..." );
            return 0;
        }

    };
    // end 声明并实现 接口的stub对象
}

client端的实现

client 端工作

实现发起绑定逻辑,并在绑定完成的回调中拿到 IBinder 类型的参数,并通过 Stub.asInterfac 函数转变为代理类实例,用 aidl 接口依赖。

源码:

// MainActivity.java

    private IBookManager mIBookManager;

    // 创建跟服务端的连接
    private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            // 获取远程服务Binder的代理:service
            Log.d("guohao","onServiceConnected");
            // service 转化为 本地的 mIBookManager 接口
            // asInterface 返回的是代理类 IBookManager.Stub.Proxy
            // 通过 IBookManager 接口依赖
            mIBookManager = IBookManager.Stub.asInterface(service);
            // 注意:本地的 IBookManager 接口,只定义了两个函数,
            // 而服务端的  IBookManager 接口,定义了三个函数,
            // 但是,这里不会因为函数不一致而报错
        }
        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.d("guohao","onServiceDisconnected");
        }
    };
    // end 创建跟服务端的连接

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    // 发起绑定服务
    private boolean bindBookService(){
        Intent intent = new Intent();
        // 指定 action,要绑定的服务类,在服务端的清单文件里定义
        intent.setAction("com.guohao.aidl.server.aidlService");
        // 指定 包名,服务端的包名
        intent.setPackage("com.guohao.aidlserver");
        startService(intent);
        return bindService(intent, mConnection, BIND_AUTO_CREATE);
    }
    // end 发起绑定服务

    public void test(View v){
        Log.d("guohao","test2");
        // 调用 绑定服务
        boolean b = bindBookService();
        if(b){
            Toast.makeText(this,"bind succ",Toast.LENGTH_SHORT).show();
        }else{
            Toast.makeText(this,"bind fail",Toast.LENGTH_SHORT).show();
        }
    }

    public void test2(View v){
        Log.d("guohao","test2");
        if(mIBookManager == null) {
            Log.d("guohao","未绑定服务");
            Toast.makeText(this,"未绑定服务" ,Toast.LENGTH_SHORT).show();
            return;
        }
        try {
            // 发起 远程调用
            int res = mIBookManager.add(1,1);
            Log.d("guohao","res = " + res);
            Toast.makeText(this,"mIBookManager.add(1,1) = " + res,Toast.LENGTH_SHORT).show();

        } catch (RemoteException e) {
            Log.d("guohao","e = " + e.toString());
            e.printStackTrace();
        }

    }

时序图小结

简单的绑定过程:

aidlclient aidlserver intent.setAction("com.guohao.aidl.server.aidlService") intent.setPackage("com.guohao.aidlserver") bindService(intent, mConnection, BIND_AUTO_CREATE) onBind 实现 IBookManager 的三个接口函数 conn.onServiceConnected( service ) aidlclient aidlserver

详细的绑定过程:

aidlclient ContextImpl AMS ActivtyThread aidlserver intent.setAction("com.guohao.aidl.server.aidlService") intent.setPackage("com.guohao.aidlserver") 3,ContextWrapper.bindService(intent, conn, BIND_AUTO_CREATE) sd = mPackageInfo.getServiceDispatcher(conn, mPackageInfo 就是 LoadedApk 在 LoadedApk 的 getServiceDispatcher 函数中: sd = new ServiceDispatcher(conn, context, mServices.put(context, map),context 是某个Activity map.put(conn, sd) return sd.getIServiceConnection ServiceDispatcher getIServiceConnection 函数中: mIServiceConnection = new InnerConnection(this) mConnection = conn return mIServiceConnection 即 sd 就是 InnerConnection bindService( token, intent, sd , ...) ConnectionRecord c = new ConnectionRecord( ... , sd , ... ) 8,app.thread.scheduleCreateService(r, r.serviceInfo) ActivtyThread.H - onCreate requestServiceBindingsLocked(r) ActivtyThread.H - onBind aidlServer = new IBookManager.Stub() 实现 IBookManager 的三个接口函数 14,(IBinder)aidlServer publishService( service = aidlServer ) ConnectionRecord c = clist.get(i) 17,c.conn.connected(r.name, service) c.conn 就是 sd,即 InnerConnection ->> InnerConnection.connected(r.name, service) ->> ServiceDispatcher.connected( service ) ->> RunConnection.run( service ) ->> ServiceDispatcher.doConnected( service ) ->> mConnection.onServiceConnected( service ) conn.onServiceConnected( service ) mIBookManager = IBookManager.Stub.asInterface(service) aidlclient ContextImpl AMS ActivtyThread aidlserver

其中 bindService 函数的 老罗的源码分析另一篇源码分析(图清楚)

小结:
conn 在 ServiceDispatcher 实例中,
ServiceDispatcher 实例在 InnerConnection 实例中,
AMS 中持有 InnerConnection 实例,
在 AMS 中通过 InnerConnection - ServiceDispatcher - RunConnection.run - conn.onServiceConnected 层层调用,完成绑定通知。


跨进程通信过程:
aidlclient (C端)IBookMana Binder 驱动 (S端)IBookM aidlserver mIBookManager.add(1,1) _data.writeInt(num1) _data.writeInt(num2) mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0) Binder 内部共享内存 onTransact case TRANSACTION_add: _arg0 = data.readInt(),_arg1 = data.readInt() int _result = this.add(_arg0, _arg1) (IBookManager.Stub)aidlServer 实现的 add 函数 aidlclient (C端)IBookMana Binder 驱动 (S端)IBookM aidlserver
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值