我是靠谱客的博主 唠叨狗,这篇文章主要介绍Android binder学习笔记(一)AIDL流程分析,现在分享给大家,希望可以做个参考。

引言

IPC,全称Inter-Process Communication,含义为进程间通信或者跨进程通信,是指两个进程之间进行数据交换的过程。
实现IPC的方法有Socket,Binder,管道等,这篇文章主要介绍Binder,通过AIDL的使用来展开分析。

有关Binder的技术文章,推荐看看下面这篇:
Android中Binder学习

AIDL

定义一个简单的AIDL接口:

复制代码
1
2
3
4
5
interface IBinderListener { void update(in String str); }

编译后,会在app/build/generated/source/aidl下生成一个IBinderListener.java的类

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
/** * {@hide} */ public interface IBinderListener extends android.os.IInterface { /** Local-side IPC implementation stub class. */ public static abstract class Stub extends android.os.Binder implements com.test.bindercserver.IBinderListener { private static final java.lang.String DESCRIPTOR = "com.test.bindercserver.IBinderListener"; /** Construct the stub at attach it to the interface. */ public Stub() { this.attachInterface(this, DESCRIPTOR); } /** * Cast an IBinder object into an com.test.bindercserver.IBinderListener interface, * generating a proxy if needed. */ public static com.test.bindercserver.IBinderListener asInterface(android.os.IBinder obj) { if ((obj==null)) { return null; } android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); if (((iin!=null)&&(iin instanceof com.test.bindercserver.IBinderListener))) { return ((com.test.bindercserver.IBinderListener)iin); } return new com.test.bindercserver.IBinderListener.Stub.Proxy(obj); } @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 { java.lang.String descriptor = DESCRIPTOR; switch (code) { case INTERFACE_TRANSACTION: { reply.writeString(descriptor); return true; } case TRANSACTION_update: { data.enforceInterface(descriptor); java.lang.String _arg0; _arg0 = data.readString(); this.update(_arg0); reply.writeNoException(); return true; } default: { return super.onTransact(code, data, reply, flags); } } } private static class Proxy implements com.test.bindercserver.IBinderListener { 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 void update(java.lang.String str) throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); try { _data.writeInterfaceToken(DESCRIPTOR); _data.writeString(str); mRemote.transact(Stub.TRANSACTION_update, _data, _reply, 0); _reply.readException(); } finally { _reply.recycle(); _data.recycle(); } } } static final int TRANSACTION_update = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0); } public void update(java.lang.String str) throws android.os.RemoteException; }

Android studio会帮我们生成这个文件,使用的时候只需要继承IBinderListener.Stub这个抽象类,在Service的onBinder()方法里面返回它,就实现了AIDL。

AIDL过程分析

主要分析一下aidl的实现过程,不依赖Android studio的编译自动生成,而是自己手动敲出接口的java文件。

首先定义接口文件

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import android.os.IBinder; import android.os.IInterface; public interface IJustKidding extends IInterface{ /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */ public int add(int a, int b) throws android.os.RemoteException; public int sub(int a, int b) throws android.os.RemoteException; static final int TRANSACTION_add = IBinder.FIRST_CALL_TRANSACTION; static final int TRANSACTION_sub = IBinder.FIRST_CALL_TRANSACTION + 1; static final String DESCRIPTOR = "com.test.BinderTest.IJustKidding"; }

add(int a, int b)和sub(int a, int b)是IJustKidding接口里面的两个方法,TRANSACTION_add 和TRANSACTION_sub 分别代表两个方法在接口文件中的排列顺序,DESCRIPTOR 作为接口的描述符。

接下来敲aidl的实现过程

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
import android.os.Binder; import android.os.IBinder; import android.os.IInterface; import android.os.Parcel; import android.os.RemoteException; import android.util.Log; public abstract class JustKiddingNative extends Binder implements IJustKidding { //JustKiddingNative相当于IJustKidding.Stub public JustKiddingNative(){ this.attachInterface(this, IJustKidding.DESCRIPTOR); } public static IJustKidding asInterface(IBinder obj){ if (obj == null){ return null; } //通过接口标识符DESCRIPTOR到本地查找 IInterface iInterface = obj.queryLocalInterface(IJustKidding.DESCRIPTOR); if (iInterface != null && iInterface instanceof IJustKidding){ Log.d("***", "same process"); //相同进程,直接返回 return (IJustKidding) iInterface; } Log.d("***", "different process"); //不同进程,返回代理类IJustKiddingProxy return new IJustKiddingProxy(obj); } //来自接口IJustKidding类的父类IInterface @Override public IBinder asBinder(){ return this; } //onTransact()方法运行在服务端 @Override public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { Log.d("***", "Stub --> onTransact()"); int arg0; int arg1; int result; switch (code){ case INTERFACE_TRANSACTION: reply.writeString(IJustKidding.DESCRIPTOR); return true; case TRANSACTION_add: Log.d("***", "Stub --> onTransact() TRANSACTION_add"); data.enforceInterface(IJustKidding.DESCRIPTOR); arg0 = data.readInt(); arg1 = data.readInt(); result = this.add(arg0, arg1); Log.d("***", "Stub --> onTransact() TRANSACTION_add result = " + result); reply.writeNoException(); reply.writeInt(result); return true; case TRANSACTION_sub: Log.d("***", "Stub --> onTransact() TRANSACTION_sub"); data.enforceInterface(IJustKidding.DESCRIPTOR); arg0 = data.readInt(); arg1 = data.readInt(); result = this.sub(arg0, arg1); Log.d("***", "Stub --> onTransact() TRANSACTION_sub result = " + result); reply.writeNoException(); reply.writeInt(result); return true; } return super.onTransact(code, data, reply, flags); } } //IJustKidding的代理类,实现了IJustKidding接口 class IJustKiddingProxy implements IJustKidding{ private IBinder mRemote; IJustKiddingProxy(IBinder iBinder){ mRemote = iBinder; } //来自接口IJustKidding类的父类IInterface @Override public IBinder asBinder() { return mRemote; } //接口描述符 public String getInterfaceDescriptor() { return IJustKidding.DESCRIPTOR; } @Override public int add(int a, int b) throws RemoteException { Log.d("***", "Proxy --> add()"); Parcel _data = Parcel.obtain(); Parcel _reply = Parcel.obtain(); int _result; try { _data.writeInterfaceToken(IJustKidding.DESCRIPTOR); Log.d("***", "Proxy --> add() --> writeInt()"); _data.writeInt(a); _data.writeInt(b); Log.d("***", "Proxy --> add() --> mRemote.transact()"); mRemote.transact(TRANSACTION_add, _data, _reply, 0); Log.d("***", "Proxy --> add() --> _reply.readException()"); _reply.readException(); _result = _reply.readInt(); } finally { _reply.recycle(); _data.recycle(); } Log.d("***", "Proxy --> add() --> _result = " + _result); return _result; } @Override public int sub(int a, int b) throws RemoteException { Log.d("***", "Proxy --> sub()"); Parcel _data = Parcel.obtain(); Parcel _reply = Parcel.obtain(); int _result; try { _data.writeInterfaceToken(IJustKidding.DESCRIPTOR); Log.d("***", "Proxy --> sub() --> writeInt()"); _data.writeInt(a); _data.writeInt(b); Log.d("***", "Proxy --> sub() --> mRemote.transact()"); mRemote.transact(TRANSACTION_sub, _data, _reply, 0); Log.d("***", "Proxy --> sub() --> _reply.readException()"); _reply.readException(); _result = _reply.readInt(); } finally { _reply.recycle(); _data.recycle(); } Log.d("***", "Proxy --> sub() --> _result = " + _result); return _result; } }

服务端口的代码就更简单了:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import android.app.Service; import android.content.Intent; import android.content.pm.PackageManager; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; public class JustKiddingService extends Service { public JustKiddingService() {} //JustKiddingNative相当于IJustKidding.Stub private final JustKiddingNative mBinder = new JustKiddingNative() { @Override public int add(int a, int b) throws RemoteException { Log.d("***", "JustKiddingService IJustKiddingInterface.Stub --> add()"); return a + b; } @Override public int sub(int a, int b) throws RemoteException { Log.d("***", "JustKiddingService IJustKiddingInterface.Stub --> sub()"); return a - b; } }; @Override public IBinder onBind(Intent intent) { // TODO: Return the communication channel to the service. Log.d("***", "JustKiddingService --> onBind()"); return mBinder; } }

客户端重点部分的代码:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
private IBinder mPlusBinder; private IJustKidding iJustKidding; private ServiceConnection serviceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName componentName, IBinder iBinder) { Log.d("***", "onServiceConnected() componentName = " + componentName + " iBinder = " + iBinder); mPlusBinder = iBinder; try { iBinder.linkToDeath(deathRecipient, 0); } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName componentName) { Log.d("***", "onServiceDisconnected() componentName = " + componentName); mPlusBinder = null; iJustKidding = null; } }; IBinder.DeathRecipient deathRecipient = new IBinder.DeathRecipient() { @Override public void binderDied() { if (iJustKidding == null){ return; } iJustKidding.asBinder().unlinkToDeath(deathRecipient, 0); iJustKidding = null; bindService(); } }; public void bindService(){ Intent intent = new Intent(this, JustKiddingService.class); bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE); } //客户端调用add()和sub()方法 if (mPlusBinder != null){ try { iJustKidding = JustKiddingNative.asInterface(mPlusBinder); if (iJustKidding != null) { int add = iJustKidding.add(2, 1); int sub = iJustKidding.sub(2, 1); Log.d("***", "add = " + add + " sub = " + sub); } } catch (RemoteException e) { e.printStackTrace(); } }

调用bindService()后,会在ServiceConnection对象的onServiceConnected()方法中回调,返回IBInder对象,可以理解为IJustKidding接口的句柄,是由驱动返回的。
然后调用JustKiddingNative.asInterface(mPlusBinder)方法(这里的JustKiddingNative相当于IJustKidding.Stub),将IBInder句柄转换为本地对象或代理对象。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static IJustKidding asInterface(IBinder obj){ if (obj == null){ return null; } IInterface iInterface = obj.queryLocalInterface(IJustKidding.DESCRIPTOR); if (iInterface != null && iInterface instanceof IJustKidding){ Log.d("***", "same process"); return (IJustKidding) iInterface; } Log.d("***", "different process"); return new IJustKiddingProxy(obj); }

根据IBinder的obj对象,现在本地查找,如果能找到,就强制转换为IJustKidding对象,然后返回;如果不能找到,就返回接口的代理对象IJustKiddingProxy,传参obj。

分别设置JustKiddingService服务为相同进程和不同进程,抓取日志,分析流程。
设置不同进程,只需要在标签中增加android:process=":remote"属性值,进程名remote可以自己取。

不同进程:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
2021-07-12 09:38:04.846 31620-31620/com.Test D/djw: BinderTestActivity --> bindService() 2021-07-12 09:38:05.162 31724-31724/? D/djw: JustKiddingService --> onBind() 2021-07-12 09:38:05.165 31620-31620/com.Test D/djw: onServiceConnected() componentName = ComponentInfo{com.Test/com.test.BinderTest.JustKiddingService} iBinder = android.os.BinderProxy@a208bfb 2021-07-12 09:39:10.403 31620-31620/com.Test D/djw: different process 2021-07-12 09:39:10.404 31620-31620/com.Test D/djw: Proxy --> add() 2021-07-12 09:39:10.404 31620-31620/com.Test D/djw: Proxy --> add() --> writeInt() 2021-07-12 09:39:10.404 31620-31620/com.Test D/djw: Proxy --> add() --> mRemote.transact() 2021-07-12 09:39:10.405 31724-31737/com.Test:remote D/djw: Stub --> onTransact() 2021-07-12 09:39:10.405 31724-31737/com.Test:remote D/djw: Stub --> onTransact() TRANSACTION_add 2021-07-12 09:39:10.405 31724-31737/com.Test:remote D/djw: JustKiddingService IJustKiddingInterface.Stub --> add() 2021-07-12 09:39:10.405 31724-31737/com.Test:remote D/djw: Stub --> onTransact() TRANSACTION_add result = 3 2021-07-12 09:39:10.406 31620-31620/com.Test D/djw: Proxy --> add() --> _reply.readException() 2021-07-12 09:39:10.406 31620-31620/com.Test D/djw: Proxy --> add() --> _result = 3 2021-07-12 09:39:10.406 31620-31620/com.Test D/djw: Proxy --> sub() 2021-07-12 09:39:10.406 31620-31620/com.Test D/djw: Proxy --> sub() --> writeInt() 2021-07-12 09:39:10.406 31620-31620/com.Test D/djw: Proxy --> sub() --> mRemote.transact() 2021-07-12 09:39:10.406 31724-31737/com.Test:remote D/djw: Stub --> onTransact() 2021-07-12 09:39:10.406 31724-31737/com.Test:remote D/djw: Stub --> onTransact() TRANSACTION_sub 2021-07-12 09:39:10.407 31724-31737/com.Test:remote D/djw: JustKiddingService IJustKiddingInterface.Stub --> sub() 2021-07-12 09:39:10.407 31724-31737/com.Test:remote D/djw: Stub --> onTransact() TRANSACTION_sub result = 1 2021-07-12 09:39:10.407 31620-31620/com.Test D/djw: Proxy --> sub() --> _reply.readException() 2021-07-12 09:39:10.408 31620-31620/com.Test D/djw: Proxy --> sub() --> _result = 1 2021-07-12 09:39:10.408 31620-31620/com.Test D/djw: add = 3 sub = 1

日志第一行和第二行,可以知道调用方和JustKiddingService不在同一进程,第五行的日志different process也能说明它们不在同一进程;
调用binderServer()之后,JustKiddingService服务的onBind()会被调用,返回接口的IBinder对象。

调用JustKiddingNative.asInterface(mPlusBinder)时,返回的是IJustKiddingProxy代理对象,add()里面_data写入接口描述符和参数数据,再调用mRemote.transact(TRANSACTION_add, _data, _reply, 0)方法,mRemote是驱动返回的IBInder句柄。

_data数据被Parcel序列化之后,经过Native、驱动,进入内核态,挂起等待返回。驱动完成一系列操作之后,唤醒Server进程,调用Server进程本地对象的onTransact方法(onTransact()方法运行在Server端),然后根据方法在接口中的顺序标识符识别到相应的方法,鉴别接口描述符,取出对应参数进行计算,调用到JustKiddingService里面JustKiddingNative实例对象的add()方法,计算完成返回结果,由replyParcel序列化后,返回结果到调用端,这样就完成了一次跨进程调用。

这里涉及到Binder驱动的流程,没有展开来讲解,有兴趣的可以看看文章开头提到的技术文章。

同一进程

复制代码
1
2
3
4
5
6
7
8
2021-07-12 11:52:29.256 3615-3615/com.Test D/djw: BinderTestActivity --> bindService() 2021-07-12 11:52:29.279 3615-3615/com.Test D/djw: JustKiddingService --> onBind() 2021-07-12 11:52:29.359 3615-3615/com.Test D/djw: onServiceConnected() componentName = ComponentInfo{com.Test/com.test.BinderTest.JustKiddingService} iBinder = com.szzt.test.BinderTest.JustKiddingService$1@6b50a0b 2021-07-12 11:52:32.437 3615-3615/com.Test D/djw: same process 2021-07-12 11:52:32.438 3615-3615/com.Test D/djw: JustKiddingService IJustKiddingInterface.Stub --> add() 2021-07-12 11:52:32.438 3615-3615/com.Test D/djw: JustKiddingService IJustKiddingInterface.Stub --> sub() 2021-07-12 11:52:32.438 3615-3615/com.Test D/djw: add = 3 sub = 1

相同进程的情况下,直接调用到JustKiddingService里面JustKiddingNative实例对象的add()方法。

至此,aidl调用流程分析完成。

最后

以上就是唠叨狗最近收集整理的关于Android binder学习笔记(一)AIDL流程分析的全部内容,更多相关Android内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(78)

评论列表共有 0 条评论

立即
投稿
返回
顶部