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 }

 

 

 

posted @ 2021-04-23 18:39  f9q  阅读(90)  评论(0编辑  收藏  举报