Native Binder
1.架构
1.1 架构
1.2 native层
1.3 内核层
2. 使用方法
一个进程得到另一个进程的binder后,就可以通过这个binder给对方发消息。通常通过服务组件得到binder.
2.1 发送方:IBinder.transact()
1 /** 2 * Perform a generic operation with the object. 3 * 4 * @param code The action to perform. This should 5 * be a number between {@link #FIRST_CALL_TRANSACTION} and 6 * {@link #LAST_CALL_TRANSACTION}. 7 * @param data Marshalled data to send to the target. Must not be null. 8 * If you are not sending any data, you must create an empty Parcel 9 * that is given here. 10 * @param reply Marshalled data to be received from the target. May be 11 * null if you are not interested in the return value. 12 * @param flags Additional operation flags. Either 0 for a normal 13 * RPC, or {@link #FLAG_ONEWAY} for a one-way RPC. 14 * 15 * @return Returns the result from {@link Binder#onTransact}. A successful call 16 * generally returns true; false generally means the transaction code was not 17 * understood. 18 */ 19 public boolean transact(int code, @NonNull Parcel data, @Nullable Parcel reply, int flags) 20 throws RemoteException;
关于参数
- code 通信码、下表是系统定义好的通信码,可以按它的原意使用,也可以自己定义扩展。
通信码
值
含义
FIRST_CALL_TRANSACTION 0x00000001 通信码的最小值 LAST_CALL_TRANSACTION 0x00ffffff 通信码最大值 PING_TRANSACTION ('_'<<24)|('P'<<16)|('N'<<8)|'G' 触发pingBinder() DUMP_TRANSACTION ('_'<<24)|('D'<<16)|('M'<<8)|'P' dump internal state. SHELL_COMMAND_TRANSACTION @hide ('_'<<24)|('C'<<16)|('M'<<8)|'D' execute a shell command. INTERFACE_TRANSACTION ('_'<<24)|('N'<<16)|('T'<<8)|'F' interrogate the recipient side of the transaction for
its canonical interface descriptor
TWEET_TRANSACTION ('_'<<24)|('T'<<16)|('W'<<8)|'T' send a tweet to the target object LIKE_TRANSACTION ('_'<<24)|('L'<<16)|('I'<<8)|'K' tell an app asynchronously that the caller likes it SYSPROPS_TRANSACTION /** @hide */ ('_'<<24)|('S'<<16)|('P'<<8)|'R' @UnsupportedAppUsage 自定义的 ... ...
- data 传输的数据
- reply 同步调用时回复的数据
- flags 通信的标记,只能是 0 或者 FLAG_ONEWAY
标记码 值 含义 0 0 a normal RPC :发完消息后后,等onTransact执行完返回后,才断续执行。reply内有回复。 FLAG_ONEWAY 1 a one-way RPC :单向的发完消息后立刻返回,断续执行,不接收reply的回复。
示例代码:
1 var value1 = 100 2 val code = IMyAidl.BINDER_HTTP_DOWNLOAD 3 val data = Parcel.obtain() 4 val reply = Parcel.obtain() 5 val flags = 0 /*Binder.FLAG_ONEWAY*/ 6 data.writeInt(value1) 7 val ret = binder?.transact(code,data,reply,flags) 8 val value2 = reply.readInt() 9 Log.e("AidlBinder","transact = $ret,data.value = $value1,reply.value = ${value2},flags = $flags")
2.2 接收方:Binder.onTransact()
1 /** 2 * Default implementation is a stub that returns false. You will want 3 * to override this to do the appropriate unmarshalling of transactions. 4 * 5 * <p>If you want to call this, call transact(). 6 * 7 * <p>Implementations that are returning a result should generally use 8 * {@link Parcel#writeNoException() Parcel.writeNoException} and 9 * {@link Parcel#writeException(Exception) Parcel.writeException} to propagate 10 * exceptions back to the caller.</p> 11 * 12 * @param code The action to perform. This should 13 * be a number between {@link #FIRST_CALL_TRANSACTION} and 14 * {@link #LAST_CALL_TRANSACTION}. 15 * @param data Marshalled data being received from the caller. 16 * @param reply If the caller is expecting a result back, it should be marshalled 17 * in to here. 18 * @param flags Additional operation flags. Either 0 for a normal 19 * RPC, or {@link #FLAG_ONEWAY} for a one-way RPC. 20 * 21 * @return Return true on a successful call; returning false is generally used to 22 * indicate that you did not understand the transaction code. 23 */ 24 protected boolean onTransact(int code, @NonNull Parcel data, @Nullable Parcel reply,int flags) throws RemoteException
示例代码:
1 class AidlBinder : IMyAidl.Stub() { 2 3 //... 4 5 /* Return true on a successful call; 6 * returning false is generally used to indicate that you did not understand the transaction code. 7 */ 8 override fun onTransact(code: Int, data: Parcel, reply: Parcel?, flags: Int): Boolean { 9 when(code){ 10 //系统定义的 11 Binder.FIRST_CALL_TRANSACTION -> { 12 13 } 14 Binder.LAST_CALL_TRANSACTION -> { 15 16 } 17 Binder.FLAG_ONEWAY -> { 18 19 } 20 Binder.TWEET_TRANSACTION -> { 21 22 } 23 Binder.INTERFACE_TRANSACTION -> { 24 25 } 26 Binder.LIKE_TRANSACTION -> { 27 28 } 29 //... 30 31 //自定义 32 IMyAidl.BINDER_HTTP_DOWNLOAD -> { 33 // SystemClock.sleep(1000 * 10) 34 val value1 = data.readInt() 35 val value2 = value1 + 1 36 reply?.writeInt(value1) 37 Log.e("AidlBinder","onTransact code = $code,data.value = ${value1},reply.value = ${value2},flags = $flags") 38 } 39 } 40 return true 41 } 42 //... 43 }
3.示例代码
1 #include <jni.h> 2 #include <errno.h> 3 #include <stdlib.h> 4 #include <stdio.h> 5 #include <unistd.h> 6 #include <sys/stat.h> 7 #include <sys/mman.h> 8 #include <fcntl.h> 9 #include <string.h> 10 #include <android/log.h> 11 12 #include "util.h" 13 14 #define BINDER_FILE "/sdcard/nbinder" 15 #define SIZE 4096 16 17 typedef struct NBinder{ 18 int8_t *ptr; 19 int length; 20 int fd ; 21 }Binder; 22 23 Binder 24 openBinder(){ 25 Binder binder; 26 binder.fd = open(BINDER_FILE,O_RDWR | O_CREAT ,S_IRWXU); 27 ftruncate(binder.fd,SIZE); 28 binder.ptr = (int8_t*) mmap(NULL,SIZE,PROT_READ | PROT_WRITE,MAP_SHARED,binder.fd,0); 29 return binder; 30 } 31 32 void 33 closeBinder(Binder binder){ 34 munmap(binder.ptr,SIZE); 35 close(binder.fd); 36 } 37 38 JNIEXPORT void JNICALL 39 Java_com_example_sjjg_binder_nb_NativeBinder_transact(JNIEnv *env, jobject thiz, 40 jint code,jstring jData, jstring jReply, jint flags) { 41 42 char *data = (char*)malloc(SIZE); 43 char *ds = jstring2Char(env,jData); 44 char *reply = jstring2Char(env,jReply); 45 Binder binder ; 46 int offset = 0; 47 48 binder = openBinder(); 49 50 sprintf(data,"code = %d,data = %s,reply = %s,flags = %d",code,ds,reply,flags); 51 52 binder.length = strlen(data); 53 54 memcpy(binder.ptr,&binder.length,sizeof(binder.length )); 55 56 offset += sizeof(binder.length) ; 57 58 memcpy(binder.ptr + offset,data,binder.length); 59 60 LOGE(TAG,"transact : %s",data); 61 62 closeBinder(binder); 63 } 64 65 JNIEXPORT void JNICALL 66 Java_com_example_sjjg_binder_nb_NativeBinder_onTransact(JNIEnv *env, jobject thiz, 67 jint code,jstring jdata, jstring reply, jint flags) { 68 Binder binder ; 69 int offset = 0; 70 char * data = (char *)malloc(SIZE); 71 72 binder = openBinder(); 73 74 memcpy(&binder.length,binder.ptr,sizeof(binder.length )); 75 76 offset += sizeof(binder.length ) ; 77 78 memcpy(data,binder.ptr + offset,SIZE); 79 80 LOGE(TAG,"read >>> len = %d, %s",binder.length,data); 81 }