使用AIDL分析Binder的工作机制
2016-05-06 10:21
549 查看
在aidl中也可以自定义类型。
写两个aidl文件:
IBookManager.aidl
在aidl中声明Book,Book.aidl
在服务端,通过Binder返回远程服务对象Stub。而这个Stub实现了aidl接口中的内容并继承Binder。
而在客户端,通过绑定一个远程服务,在服务连接成功后,得到这个远程服务对象Stub。用一个aidl接口去引用。
这就是利用Service进行IPC的大概内容。
观察aidl文件编译后的java文件的内容:
aidl接口和aidl文件中的内容一致。有两个抽象方法,这就是在aidl文件中定义的方法。
可以发现Stub实现了aidl接口,继承自Binder。
Stub中的两个final类型的静态变量
TRANSACTION_getBookList和TRANSACTION_add
DESCRIPTOR:Stub的唯一标识
先前说,在客户端通过asInterface,把获取的Binder对象转换为Stub远程服务实例,通过一个aidl的接口引用。
但asInterface返回的却不一定是Stub。
在此方法中,会判断客户端和服务端是否位于同一个进程,如果是,返回的是stub对象本身,否则返回的是Stub的Proxy。
在代理模式中,代理Proxy和真实对象往往实现同一个接口,代理对象握有真实对象的引用,以便操作真实对象。
Proxy同样实现了aidl接口,把Stub对象实例传递到Proxy中。
当客户端调用getBookList,实际调用的是Proxy中的getBookList。在方法中,
声明了Parcel的输入对象_data,Parcel的输出对象_reply。
调用transact方法来发起RPC(远程过程调用)请求,同时当前线程挂起,然后服务端的Stub的onTransact执行。(onTransact运行在Binder线程池中)
在onTransact中通过code判断是哪个方法执行,然后就会执行Stub的getBookList方法。当方法执行完毕后,会把结果写入到reply中,返回true表示客户端的远程调用成功,否则失败。
而直到RPC结束,客户端的线程才继续执行,从_reply中取出RPC的返回结果,最后返回_reply中的数据。
当足够了解了Binder,其实也可以不借助aidl工具。写aidl的目的只是为了更方便更快速的实现Binder。
不写aidl的话,需要手写接口,Stub,Proxy。在客户端同样也不需要写aidl,直接拷贝手写的java文件。
写两个aidl文件:
IBookManager.aidl
interface IBookManager { void add(in Book book); List<Book> getBookList(); }
在aidl中声明Book,Book.aidl
parcelable Book;
在服务端,通过Binder返回远程服务对象Stub。而这个Stub实现了aidl接口中的内容并继承Binder。
而在客户端,通过绑定一个远程服务,在服务连接成功后,得到这个远程服务对象Stub。用一个aidl接口去引用。
这就是利用Service进行IPC的大概内容。
观察aidl文件编译后的java文件的内容:
package com.asule.cn; public interface IBookManager extends android.os.IInterface{ //我们在aidl接口 public java.util.List<com.asule.cn.Book> getBookList() throws android.os.RemoteException; public void add(com.asule.cn.Book book) throws android.os.RemoteException; //-----------------Stub-----------------------> public static abstract class Stub extends android.os.Binder implements com.asule.cn.IBookManager{ static final int TRANSACTION_getBookList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0); static final int TRANSACTION_add = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1); //binder的唯一标识 private static final java.lang.String DESCRIPTOR = "com.asule.cn.IBookManager"; public Stub(){ this.attachInterface(this, DESCRIPTOR); } public static com.asule.cn.IBookManager asInterface(android.os.IBinder obj){ if ((obj==null)) { return null; } android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); if (((iin!=null)&&(iin instanceof com.asule.cn.IBookManager))) { return ((com.asule.cn.IBookManager)iin); } return new com.asule.cn.IBookManager.Stub.Proxy(obj); } //返回Stub句柄 @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_getBookList:{ data.enforceInterface(DESCRIPTOR); java.util.List<com.asule.cn.Book> _result = this.getBookList(); reply.writeNoException(); reply.writeTypedList(_result); return true; } case TRANSACTION_addBook:{ data.enforceInterface(DESCRIPTOR); com.asule.cn.Book _arg0; if ((0!=data.readInt())) { _arg0 = com.asule.cn.Book.CREATOR.createFromParcel(data); } else { _arg0 = null; } this.addBook(_arg0); reply.writeNoException(); return true; } } return super.onTransact(code, data, reply, flags); } //-----------------Proxy-----------------------> //Stub的内部类Proxy private static class Proxy implements com.asule.cn.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 java.util.List<com.asule.cn.Book> getBookList() throws android.os.RemoteException{ // android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); java.util.List<com.asule.cn.Book> _result; try { _data.writeInterfaceToken(DESCRIPTOR); mRemote.transact(Stub.TRANSACTION_getBookList, _data, _reply, 0); _reply.readException(); _result = _reply.createTypedArrayList(com.asule.cn.Book.CREATOR); } finally { _reply.recycle(); _data.recycle(); } return _result; } @Override public void add(com.asule.cn.Book book) throws android.os.RemoteException{ android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); try { _data.writeInterfaceToken(DESCRIPTOR); if ((book!=null)) { _data.writeInt(1); book.writeToParcel(_data, 0); } else { _data.writeInt(0); } mRemote.transact(Stub.TRANSACTION_addBook, _data, _reply, 0); _reply.readException(); } finally { _reply.recycle(); _data.recycle(); } } } //<-----------------Proxy----------------------- } //<-----------------Stub----------------------- }
aidl接口和aidl文件中的内容一致。有两个抽象方法,这就是在aidl文件中定义的方法。
可以发现Stub实现了aidl接口,继承自Binder。
Stub中的两个final类型的静态变量
TRANSACTION_getBookList和TRANSACTION_add
DESCRIPTOR:Stub的唯一标识
先前说,在客户端通过asInterface,把获取的Binder对象转换为Stub远程服务实例,通过一个aidl的接口引用。
但asInterface返回的却不一定是Stub。
在此方法中,会判断客户端和服务端是否位于同一个进程,如果是,返回的是stub对象本身,否则返回的是Stub的Proxy。
在代理模式中,代理Proxy和真实对象往往实现同一个接口,代理对象握有真实对象的引用,以便操作真实对象。
Proxy同样实现了aidl接口,把Stub对象实例传递到Proxy中。
当客户端调用getBookList,实际调用的是Proxy中的getBookList。在方法中,
声明了Parcel的输入对象_data,Parcel的输出对象_reply。
调用transact方法来发起RPC(远程过程调用)请求,同时当前线程挂起,然后服务端的Stub的onTransact执行。(onTransact运行在Binder线程池中)
在onTransact中通过code判断是哪个方法执行,然后就会执行Stub的getBookList方法。当方法执行完毕后,会把结果写入到reply中,返回true表示客户端的远程调用成功,否则失败。
而直到RPC结束,客户端的线程才继续执行,从_reply中取出RPC的返回结果,最后返回_reply中的数据。
当足够了解了Binder,其实也可以不借助aidl工具。写aidl的目的只是为了更方便更快速的实现Binder。
不写aidl的话,需要手写接口,Stub,Proxy。在客户端同样也不需要写aidl,直接拷贝手写的java文件。
相关文章推荐
- 在MVC中使用async和await的说明
- 219. Contains Duplicate II
- LeetCode 220. Contains Duplicate III(检查重复)
- [Util] can not load library from so file +++ register push fail. token:null, errCode:10004,msg:COD
- LeetCode 219. Contains Duplicate II(检查重复)
- LeetCode 217. Contains Duplicate(检查重复)
- 真机上装不上测试应用,Installation error: INSTALL_FAILED_INSUFFICIENT_STORAGE
- maven/jekinsFailed to connect to repository : Command
- TensorFlow教程05:MNIST深度学习初探
- LeetCode------Climbing Stairs
- KairosDB 安装与入门
- HDU 1151 Air Raid(最小路径覆盖)
- http://www.cnblogs.com/tangkai/p/4172922.html
- 安卓aidl的详细讲解(终极讲解)
- 页面渲染——简化paint复杂程度和区域
- TIME_WAIT状态
- 修复 Sync with Gradle for project ' ' failed: 拒绝连接问题
- 多线程—wait,notify(针对方法synchronized)
- http://blog.csdn.net/welovesunflower/article/details/51202313
- pthread_cond_wait()用法分析