Andorid中AIDL解析

概述

AIDL是android接口定义语言,可以利用它定义客户端与服务端进行进程间通信 (IPC) 时都认可的编程接口。跨进程通信,不同的进程,运行在不同的VM虚拟机上,每个进程都有独立的内存空间,管理各自的数据,就像“我住长江头,君住长江尾。日日思君不见君,共饮长江水”。AIDL就是“我”与“君”沟通的桥梁。

关键词

Binder
AIDL:
序列化
Stub类: 字面上的翻译是存根的意思.
Proxy类:字面上的翻译是代理的意思.Stub的内部代理类Proxy。
Transaction:字面上的翻译是交易合同合约的意思.
AIDL机制

AIDL机制的核心是对aidl文件进行编译后的编译中间件java文件,上述原理图中都是在该java文件中实现,因此分析AIDL机制的重点放在对此文件的分析中.

AIDL通讯为双工,双向通讯,但还是要分为服务端和客户端两个方面:

服务端的工作:
a) 创建一个Service用来监听客户端的连接请求
b) 创建一个AIDL文件,将暴露给客户端的接口在这个AIDL文件中声明
c) 在Service中实现AIDL中定义的接口

客户端工作:
a)绑定服务端
b) 绑定成功后,将服务端返回的Binder对象转成AIDL接口所属类型
c) 调用服务端接口

使用AIDL时需要注意以下几点: 参考
1、当非跨进程时(在Manifest没有指定process属性),当客户端调用AIDL方法时,客户端在UI线程,那么被调用的服务端的方法也在UI线程。反之。如果。客户端调用AIDL方法时,客户端在非UI线程,那么被调用的服务端方法也在非UI线程。
2、当跨进程时(在Manifest指定process属性),服务端的方法运行在Binder的线程池中,所以Binder方法不管是否耗时都应该采用同步的方式去实现。
3、当客户端发起远程请求时,由于当前线程会被挂起直至服务端进程返回数据,所以如果一个远程方法是很耗时的,那么不能再UI线程中发起此远程请求。
4、如果一个远程方法是耗时的,在客户端调用时会被挂起(上面说的第3点)。但是如果远程方法返回void,也就是远程方法在怎么耗时,客户端也不需要你返回数据,那么可以在AIDL方法中增加oneway关键字。
oneway void addBook(in Book book) 这样客户端就不会被挂起了。
5、在跨进程中,客户端传递的对象是经过序列化的,在服务端接收的对象,是经过反序列化的。服务端接收的对象只是里面的东西一样,但是根本不是同一个对象,这点要注意。
6、所有非原语(原语含义看下面)参数都需要指示数据走向的方向标记。可以是 in、out 或 inout。
原语默认为 in,不能是其他方向。
7、AIDL接口中只支持方法,不支持声明静态常量。

使用

拿IKeyguardService.aidl来举例
使用AIDL完成通讯需要经过如下几个步骤:
1) 创建 aidl 接口文件
2) 创建一个远程 Service
3) 客户端链接Binder
下面文字参考

创建 aidl 接口文件

支持的参数类型

  1. 八种基本数据类型;
  2. String、CharSequence;
  3. List、Map,它们中的数据类型也应该是AIDL支持的;
  4. 实现Parcelabel的引用类型。

自定义引用类型使用

如果要使用自定义的数据类型,需要先为它也生成一个aidl文件,里面内容只需两行:

1
2
AIDL的包名;
parcelable 类名;

例如:

1
2
package com.coorchice.coorchicelibone;
parcelable Role;

接着就可以创建对应的java数据类了,然后实现Parcelable接口,注意包名需要和aidl一模一样!如果你对自定义类型使用了in或者inout标识符的话,你必须再给自定义类实现readFromParcel()方法。比如:

1
2
3
4
public void readFromParcel(Parcel in) {
name = in.readString();
skill = in.readString();
}

然后在定义aidl接口时,一定要记得手动写一下自定义引用类的import!

参数修饰符

•in: 表示参数数据只能由客户端传递到服务端,基本类型就默认只支持in修饰符。
•out:表示参数数据只能由服务端传递到客户端。即服务端如果修改了参数对象的值,那么客户端的值也会变化,但是服务端无法读取到客户端对象的值。
•inout:表示参数数据能够双向传递。

定义服务接口

现在,我们可以开始定义服务接口了!这里定义的服务接口就是后面我们需要在客户端调用的。我们以SystemUI模块中的IRecentsSystemUserCallbacks.aidl为例来讲解
frameworks/base/packages/SystemUI/src/com/android/systemui/recents/IRecentsSystemUserCallbacks.aidl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.android.systemui.recents;

import android.graphics.Rect;

/**
* Due to the fact that RecentsActivity is per-user, we need to establish an
* interface (this) for the non-system user to register itself for callbacks and to
* callback to the system user to update internal state.
*/
oneway interface IRecentsSystemUserCallbacks {
void registerNonSystemUserCallbacks(IBinder nonSystemUserCallbacks, int userId);

void updateRecentsVisibility(boolean visible);
void startScreenPinning(int taskId);
void sendRecentsDrawnEvent();
void sendDockingTopTaskEvent(int dragMode, in Rect initialRect);
void sendLaunchRecentsEvent();
void setWaitingForTransitionStartEvent(boolean waitingForTransitionStart);
}

注意:自定义的类必须加in、out、inout等标识符,否则会报错!

实例
frameworks/base/core/java/android/bluetooth/le/PeriodicAdvertisingReport.java
frameworks/base/core/java/android/bluetooth/le/IPeriodicAdvertisingCallback.aidl

编译后生成的类解析

编译之后编译器自动帮我们生成了一个服务接口类名.Stub的抽象类,它继承自Binder,然后实现了我们定义的服务接口(注意我们的服务接口实现了IInterface接口)。嗯,重点是它是一个Binder!它就是我们用来进行Binder通讯的!

*.aidl文件如何被编译器编译后生成*.java文件的,请参考

其实,Android的AIDL就是让编译器帮助我们生成一个实现了我们接口的Binder,以帮助我们简化开发。当然,如果你了解原理的话,也可以自己写。

下面我们一步一步来看看这编译器生成的类都有些什么?
out/target/common/obj/APPS/SystemUI_intermediates/src/com/android/systemui/recents/IRecentsSystemUserCallbacks.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
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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
/*
* This file is auto-generated. DO NOT MODIFY.
* Original file: frameworks/base/packages/SystemUI/src/com/android/systemui/recents/IRecentsSystemUserCallbacks.aidl
*/
package com.android.systemui.recents;
/**
* Due to the fact that RecentsActivity is per-user, we need to establish an
* interface (this) for the non-system user to register itself for callbacks and to
* callback to the system user to update internal state.
*/
public interface IRecentsSystemUserCallbacks extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements com.android.systemui.recents.IRecentsSystemUserCallbacks
{
private static final java.lang.String DESCRIPTOR = "com.android.systemui.recents.IRecentsSystemUserCallbacks";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an com.android.systemui.recents.IRecentsSystemUserCallbacks interface,
* generating a proxy if needed.
*/
public static com.android.systemui.recents.IRecentsSystemUserCallbacks asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.android.systemui.recents.IRecentsSystemUserCallbacks))) {
return ((com.android.systemui.recents.IRecentsSystemUserCallbacks)iin);
}
return new com.android.systemui.recents.IRecentsSystemUserCallbacks.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
{
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_registerNonSystemUserCallbacks:
{
data.enforceInterface(DESCRIPTOR);
android.os.IBinder _arg0;
_arg0 = data.readStrongBinder();
int _arg1;
_arg1 = data.readInt();
this.registerNonSystemUserCallbacks(_arg0, _arg1);
return true;
}
case TRANSACTION_updateRecentsVisibility:
{
data.enforceInterface(DESCRIPTOR);
boolean _arg0;
_arg0 = (0!=data.readInt());
this.updateRecentsVisibility(_arg0);
return true;
}
case TRANSACTION_startScreenPinning:
{
data.enforceInterface(DESCRIPTOR);
int _arg0;
_arg0 = data.readInt();
this.startScreenPinning(_arg0);
return true;
}
case TRANSACTION_sendRecentsDrawnEvent:
{
data.enforceInterface(DESCRIPTOR);
this.sendRecentsDrawnEvent();
return true;
}
case TRANSACTION_sendDockingTopTaskEvent:
{
data.enforceInterface(DESCRIPTOR);
int _arg0;
_arg0 = data.readInt();
android.graphics.Rect _arg1;
if ((0!=data.readInt())) {
_arg1 = android.graphics.Rect.CREATOR.createFromParcel(data);
}
else {
_arg1 = null;
}
this.sendDockingTopTaskEvent(_arg0, _arg1);
return true;
}
case TRANSACTION_sendLaunchRecentsEvent:
{
data.enforceInterface(DESCRIPTOR);
this.sendLaunchRecentsEvent();
return true;
}
case TRANSACTION_setWaitingForTransitionStartEvent:
{
data.enforceInterface(DESCRIPTOR);
boolean _arg0;
_arg0 = (0!=data.readInt());
this.setWaitingForTransitionStartEvent(_arg0);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}

private static class Proxy implements com.android.systemui.recents.IRecentsSystemUserCallbacks
{
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 registerNonSystemUserCallbacks(android.os.IBinder nonSystemUserCallbacks, int userId) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeStrongBinder(nonSystemUserCallbacks);
_data.writeInt(userId);
mRemote.transact(Stub.TRANSACTION_registerNonSystemUserCallbacks, _data, null, android.os.IBinder.FLAG_ONEWAY);
}
finally {
_data.recycle();
}
}

@Override public void updateRecentsVisibility(boolean visible) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(((visible)?(1):(0)));
mRemote.transact(Stub.TRANSACTION_updateRecentsVisibility, _data, null, android.os.IBinder.FLAG_ONEWAY);
}
finally {
_data.recycle();
}
}

@Override public void startScreenPinning(int taskId) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(taskId);
mRemote.transact(Stub.TRANSACTION_startScreenPinning, _data, null, android.os.IBinder.FLAG_ONEWAY);
}
finally {
_data.recycle();
}
}

@Override public void sendRecentsDrawnEvent() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_sendRecentsDrawnEvent, _data, null, android.os.IBinder.FLAG_ONEWAY);
}
finally {
_data.recycle();
}
}

@Override public void sendDockingTopTaskEvent(int dragMode, android.graphics.Rect initialRect) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(dragMode);
if ((initialRect!=null)) {
_data.writeInt(1);
initialRect.writeToParcel(_data, 0);
}
else {
_data.writeInt(0);
}
mRemote.transact(Stub.TRANSACTION_sendDockingTopTaskEvent, _data, null, android.os.IBinder.FLAG_ONEWAY);
}
finally {
_data.recycle();
}
}

@Override public void sendLaunchRecentsEvent() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_sendLaunchRecentsEvent, _data, null, android.os.IBinder.FLAG_ONEWAY);
}
finally {
_data.recycle();
}
}

@Override public void setWaitingForTransitionStartEvent(boolean waitingForTransitionStart) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(((waitingForTransitionStart)?(1):(0)));
mRemote.transact(Stub.TRANSACTION_setWaitingForTransitionStartEvent, _data, null, android.os.IBinder.FLAG_ONEWAY);
}
finally {
_data.recycle();
}
}
}

static final int TRANSACTION_registerNonSystemUserCallbacks = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_updateRecentsVisibility = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
static final int TRANSACTION_startScreenPinning = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
static final int TRANSACTION_sendRecentsDrawnEvent = (android.os.IBinder.FIRST_CALL_TRANSACTION + 3);
static final int TRANSACTION_sendDockingTopTaskEvent = (android.os.IBinder.FIRST_CALL_TRANSACTION + 4);
static final int TRANSACTION_sendLaunchRecentsEvent = (android.os.IBinder.FIRST_CALL_TRANSACTION + 5);
static final int TRANSACTION_setWaitingForTransitionStartEvent = (android.os.IBinder.FIRST_CALL_TRANSACTION + 6);
}
public void registerNonSystemUserCallbacks(android.os.IBinder nonSystemUserCallbacks, int userId) throws android.os.RemoteException;
public void updateRecentsVisibility(boolean visible) throws android.os.RemoteException;
public void startScreenPinning(int taskId) throws android.os.RemoteException;
public void sendRecentsDrawnEvent() throws android.os.RemoteException;
public void sendDockingTopTaskEvent(int dragMode, android.graphics.Rect initialRect) throws android.os.RemoteException;
public void sendLaunchRecentsEvent() throws android.os.RemoteException;
public void setWaitingForTransitionStartEvent(boolean waitingForTransitionStart) throws android.os.RemoteException;
}

服务接口实现IInterface

1
2
3
4
public interface IRecentsSystemUserCallbacks extends android.os.IInterface
{
...
}

编译器根据我们写的服务接口,重新生成了一个接口,唯一的区别就是新的接口继承了IInterface接口。这个接口是干什么的呢?
我们来看frameworks/base/core/java/android/os/IInterface.java的实现.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package android.os;
/**
* Base class for Binder interfaces. When defining a new interface,
* you must derive it from IInterface.
*/
public interface IInterface
{
/**
* Retrieve the Binder object associated with this interface.
* You must use this instead of a plain cast, so that proxy objects
* can return the correct result.
*/
public IBinder asBinder();
}

可以看到,它只有一个接口方法。这个方法用来定义将实现接口的类应该具备返回一个与之相关联的Binder的功能,以提供通讯能力。一般实现这个方法的类自己本身就会去继承Binder。
这样的设计使得Binder机制不用关心具体的接口是什么,只要是IInterface就行。事实上相当于是我们在IInterface接口的基础上扩展了接口功能,本质上还是一个IInterface,所以Binder能够认出它。

继承Binder,实现服务接口

要进行Binder通讯,我们自然需要一个Binder;要实现我们定义的服务接口功能,自然就需要实现服务接口。那么需要满足这两个条件怎么办?很简单,继承Binder,然后实现服务接口就行。
编译器为我们生成的类中有一个内部类Stub就是这么干的。

1
2
3
public static abstract class Stub extends android.os.Binder implements com.android.systemui.recents.IRecentsSystemUserCallbacks{
...
}

DESCRIPTOR

Binder需要绑定服务接口,定义DESCRIPTOR描述
为了一个Binder和一个特定服务接口绑定,以对外提供功能,需要给Binder定义一个DESCRIPTOR描述,表示我这个Binder是提供特定功能链接的,不是随便可以用的。
通常,DESCRIPTOR描述会直接使用包名 + 服务接口。

1
private static final java.lang.String DESCRIPTOR = "com.android.systemui.recents.IRecentsSystemUserCallbacks";

实现asInterface()供客户端调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* Cast an IBinder object into an com.android.systemui.recents.IRecentsSystemUserCallbacks interface,
* generating a proxy if needed.
*/
public static com.android.systemui.recents.IRecentsSystemUserCallbacks asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
//如果在同一个进程中,则返回IRecentsSystemUserCallbacks对象
if (((iin!=null)&&(iin instanceof com.android.systemui.recents.IRecentsSystemUserCallbacks))) {
return ((com.android.systemui.recents.IRecentsSystemUserCallbacks)iin);
}
//如果不在同一个进程中,则需要创建代理.
return new com.android.systemui.recents.IRecentsSystemUserCallbacks.Stub.Proxy(obj);
}

作为一个服务提供者,为了能够给调用者提供远程功能,自然需要能够提供和远程服务关联的Binder来通讯,请求服务。获取Binder的接口就是IInterface中定义的。
先查询一下获取到的和远程Service通讯的Binde中是否已经添加了功能接口的实现,如果没有则创建代理,通过代理间接的操作Binder和远程Service通讯,实现功能。

思考:既然我们已经获取到了能够直接和远程Service通讯的Binder,为什么不直接操作它去向远程Service请求服务呢?

确实,我们可以直接操作Binder向远程Service请求服务,但这过程中有很多繁琐的操作,还有一些code码的区别,如果不封装隔离的话,随着功能的扩展,我们将很难再去维护这段通讯逻辑。还有就是通过这种方式统一的管理通讯逻辑使得它可以随处使用,而不用没一个要用的地方都去写一遍。

既然是要代理和远程服务通讯,而且通讯的目的是为了请求服务接口定义的功能,那么很自然就能想到去实现服务接口,然后再对应的接口方法中实现逻辑即可。这样就可以分开来维护客户端和服务端的对应的每个功能了。

所以,我们的代理也需要实现服务接口,然后在代理中操作远程通讯的Binder进行通讯。

重写onTransact()

原理

先用上图整体描述这个AIDL从客户端(Client)发起请求至服务端(Server)相应的工作流程,我们可以看出整体的核心就是 Binder.如下:
AIDL机制原理

在SystemUI的Recent模块中,每个用户都拥有一个Recent模块的SystemUI进程.这里的每个用户分两种,一种是System用户,一种是访客模式的用户.
android自从把最近任务改为一个activity后,最近任务的内部逻辑的复杂程度就在不停地快速增长着。android是支持多用户的,最近任务在每个用户空间都有一个单独运行的进程。而只有主用户空间的SystemUI进程通过AIDL才能收到PhoneWindowManager发过来的事件,比如showRecents,hideRecents等,所以副用户空间的systemui进程就需要主用户空间的systemui来通知副用户的systemui来做显示最近任务和隐藏最近任务等操作。所以会在SystemUI里面看到有两次的AIDL操作.

对于SystemUser,在Recent.java中收到来自PhoneWindwoManager的showRecentApps(),hideRecentApps()等操作时,会调用RecentImpl.java来处理.
在Recent.java的onStart函数中,对于SystemUser和SecondaryUser处理如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Override
public void start() {
...
// Due to the fact that RecentsActivity is per-user, we need to establish and interface for
// the system user's Recents component to pass events (like show/hide/toggleRecents) to the
// secondary user, and vice versa (like visibility change, screen pinning).
final int processUser = sSystemServicesProxy.getProcessUser();
if (sSystemServicesProxy.isSystemUser(processUser)) {
// For the system user, initialize an instance of the interface that we can pass to the
// secondary user
getComponent(CommandQueue.class).addCallbacks(this);
mSystemToUserCallbacks = new RecentsSystemUser(mContext, mImpl);
} else {
// For the secondary user, bind to the primary user's service to get a persistent
// interface to register its implementation and to later update its state
registerWithSystemUser();
}
putComponent(Recents.class, this);
}

如果是SystemUser的话,会准备好SecondaryUser需要用到的回调mSystemToUserCallbacks,我们看RecentsSystemUser知道是一个AIDL来实现.此时通过mSystemToUserCallbacks
建立了SystemUser与SecondaryUser之间调用关系的服务端,等待客户端的调用.
如果是SecondaryUser的话,执行registerWithSystemUser函数,通过mSystemToUserCallbacks来注册RecentsImplProxy,RecentsImplProxy也是一个AIDL.

第一次:SystemUI进程与主用户的SystemUI进程之间的通信.
在IRecentsSystemUserCallbacks.aidl中
Server端:RecentsSystemUser.java
Client端:Recents.java

此次AIDL涉及到的文件有如下:
1) AIDL接口定义: frameworks/base/packages/SystemUI/src/com/android/systemui/recents/IRecentsSystemUserCallbacks.aidl
2) 编译的中间件:
out/target/common/obj/APPS/SystemUI_intermediates/src/com/android/systemui/recents/IRecentsSystemUserCallbacks.java
3) 接口的实现: frameworks/base/packages/SystemUI/src/com/android/systemui/recents/RecentsSystemUser.java
4) 接口的使用:frameworks/base/packages/SystemUI/src/com/android/systemui/recents/Recents.java

第二次:访客SystemUI进程与主用户SystemUI进程之间的通信.
Q:为何访客SystemUI进程不能直接与SystemUI进程通信????

1) 接口定义: frameworks/base/packages/SystemUI/src/com/android/systemui/recents/IRecentsNonSystemUserCallbacks.aidl
2)编译中间件:
out/target/common/obj/APPS/SystemUI_intermediates/src/com/android/systemui/recents/IRecentsNonSystemUserCallbacks.java
3)接口实现:frameworks/base/packages/SystemUI/src/com/android/systemui/recents/RecentsImplProxy.java
4)接口使用:frameworks/base/packages/SystemUI/src/com/android/systemui/recents/RecentsSystemUser.java

IRecentsNonSystemUserCallbacks.aidl中
Server端:RecentsImplProxy.java
Client端:RecentsSystemUser.java

根据原理图,我们将按照一次Client的一次远程请求的流程开始分析.

客户端接口的使用

客户端 Recent.java开始调用
frameworks/base/packages/SystemUI/src/com/android/systemui/recents/Recents.java

  1. IRecentsSystemUserCallbacks的声明

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    /**
    * An implementation of the SystemUI recents component, which supports both system and secondary
    * users.
    */
    public class Recents extends SystemUI
    implements RecentsComponent, CommandQueue.Callbacks {

    private final static String TAG = "Recents";
    ...
    // Only for secondary users, this is the callbacks instance provided by the system user to make
    // calls back
    private IRecentsSystemUserCallbacks mUserToSystemCallbacks;
  2. Client发起请求,以Recent其中的一个onBusEvent为例来分析.可以看到对于非主用户,会新起一个线程.

    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
    /**
    * Handle Recents activity visibility changed.
    */
    public final void onBusEvent(final RecentsVisibilityChangedEvent event) {
    SystemServicesProxy ssp = Recents.getSystemServices();
    int processUser = ssp.getProcessUser();//获取进程的User ID
    if (ssp.isSystemUser(processUser)) {//如果是主用户进程,直接调用RecentImpl.java里面onVisibilityChanged函数处理
    mImpl.onVisibilityChanged(event.applicationContext, event.visible);
    } else {//如果是非主用户进程,则需要新起线程处理
    postToSystemUser(new Runnable() {
    @Override
    public void run() {
    try {
    mUserToSystemCallbacks.updateRecentsVisibility(event.visible);//private IRecentsSystemUserCallbacks mUserToSystemCallbacks;
    } catch (RemoteException e) {
    Log.e(TAG, "Callback failed", e);
    }
    }
    });
    }

    // This will catch the cases when a user launches from recents to another app
    // (and vice versa) that is not in the recents stack (such as home or bugreport) and it
    // would not reset the wait for transition flag. This will catch it and make sure that the
    // flag is reset.
    if (!event.visible) {
    mImpl.setWaitingForTransitionStart(false);
    }
    }

    再看看postToSystemUser函数的实现.

    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
    /**
    * Runs the runnable in the system user's Recents context, connecting to the service if
    * necessary.
    */
    private void postToSystemUser(final Runnable onConnectRunnable) {
    mOnConnectRunnables.add(onConnectRunnable);
    if (mUserToSystemCallbacks == null) {
    Intent systemUserServiceIntent = new Intent();
    systemUserServiceIntent.setClass(mContext, RecentsSystemUserService.class);
    boolean bound = mContext.bindServiceAsUser(systemUserServiceIntent,
    mUserToSystemServiceConnection, Context.BIND_AUTO_CREATE, UserHandle.SYSTEM);
    EventLog.writeEvent(EventLogTags.SYSUI_RECENTS_CONNECTION,
    EventLogConstants.SYSUI_RECENTS_CONNECTION_USER_BIND_SERVICE,
    sSystemServicesProxy.getProcessUser());
    if (!bound) {
    // Retry after a fixed duration
    mHandler.postDelayed(new Runnable() {
    @Override
    public void run() {
    registerWithSystemUser();
    }
    }, BIND_TO_SYSTEM_USER_RETRY_DELAY);
    }
    } else {
    runAndFlushOnConnectRunnables();
    }
    }

    从上面两块代码可以看到postToSystemUser函数做了两件事件:
    a)当mUserToSystemCallbacks即IRecentsSystemUserCallbacks的对象为空时,通过bindService函数,绑定RecentsSystemUserService这个服务,我们可以从 RecentsSystemUserService的onBind函数看到,此服务调用的是Recent.java
    在bindService绑定时, 会调用主线程中的registerWithSystemUser函数,
    b)如果mUserToSystemCallbacks不为空,即对主用户进程的回调存在,则执行mUserToSystemCallbacks.updateRecentsVisibility(event.visible);调用过程下面等会儿继续讲.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//RecentsSystemUserService.java
public class RecentsSystemUserService extends Service {

private static final String TAG = "RecentsSystemUserService";
private static final boolean DEBUG = false;

@Override
public void onCreate() {
super.onCreate();
}

@Override
public IBinder onBind(Intent intent) {
SystemUIApplication app = (SystemUIApplication) getApplication();
Recents recents = app.getComponent(Recents.class);
if (DEBUG) {
Log.d(TAG, "onBind: " + recents);
}
if (recents != null) {
return recents.getSystemUserCallbacks();
}
return null;
}
}

再来看看registerWithSystemUser函数

1
2


  1. 连接服务,并绑定服务端

    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
    // Only for secondary users, this is the service connection we use to connect to the system user
    private final ServiceConnection mUserToSystemServiceConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
    if (service != null) {
    //第一步:获取IUserToSystemCallbacks对象
    mUserToSystemCallbacks = IRecentsSystemUserCallbacks.Stub.asInterface(
    service);
    //第二步:写入SYSUI_RECENTS_CONNECTION事件,此处与AIDL无关,仅写入事件
    EventLog.writeEvent(EventLogTags.SYSUI_RECENTS_CONNECTION,
    EventLogConstants.SYSUI_RECENTS_CONNECTION_USER_SYSTEM_BOUND,
    sSystemServicesProxy.getProcessUser());

    //第三步:设置主用户Binder对象代理,监听主用户的IBinder,如果死亡,则说明开始启动访客模式
    // Listen for system user's death, so that we can reconnect later
    try {
    service.linkToDeath(mUserToSystemCallbacksDeathRcpt, 0);
    } catch (RemoteException e) {
    Log.e(TAG, "Lost connection to (System) SystemUI", e);
    }

    //第四步:刷新进程中的线程
    // Run each of the queued runnables
    runAndFlushOnConnectRunnables();
    }

    // Unbind ourselves now that we've registered our callbacks. The
    // binder to the system user are still valid at this point.
    mContext.unbindService(this);
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
    // Do nothing
    }
    };

    从上述代码来看,连接服务做了四件事情,其中的重点是第二步,mUserToSystemCallbacks = IRecentsSystemUserCallbacks.Stub.asInterface(service);这句代码中我们重点关注asInterface,从后面的代码,我们可以看到我们可以IRecentsSystemUserCallbacks.Stub是IRecentsSystemUserCallbacks接口的内部抽象类.
    asInterface用于将服务端的Binder对象转换成客户端所需的AIDL接口类型的对象,这种转换过程是区分进程的【如果客户端和服务端位于同一进程,那么此方法返回的就是服务端的Stub对象本身,否则返回的是系统封装后的Stub.proxy对象】
    在 ServiceConnection 绑定服务的方法里,我们通过IRecentsSystemUserCallbacks.Stub.asInterface(service)方法 获得 IRecentsSystemUserCallbacks对象,我们跟着 asInterface 步伐看看里面有什么名堂。
    我们到编译中间件IRecentsSystemUserCallbacks.java中看下asInterface函数的实现:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    /**
    * Cast an IBinder object into an com.android.systemui.recents.IRecentsSystemUserCallbacks interface,
    * generating a proxy if needed.
    */
    public static com.android.systemui.recents.IRecentsSystemUserCallbacks asInterface(android.os.IBinder obj)
    {
    if ((obj==null)) {
    return null;
    }
    android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
    if (((iin!=null)&&(iin instanceof com.android.systemui.recents.IRecentsSystemUserCallbacks))) {
    return ((com.android.systemui.recents.IRecentsSystemUserCallbacks)iin);
    }
    return new com.android.systemui.recents.IRecentsSystemUserCallbacks.Stub.Proxy(obj);
    }

    我们看看DESCRIPTOR的定义:

    1
    private static final java.lang.String DESCRIPTOR = "com.android.systemui.recents.IRecentsSystemUserCallbacks";

    因此,可以看出如果是同一进程,那么就返回Stub对象本身(obj.queryLocalInterface(DESCRIPTOR)),否则如果是跨进程则返回Stub的代理内部类Proxy。
    也就是说这个 asInterface 方法返回的是一个远程接口具备的能力(有什么方法可以调用),在我们项目里,asInterface 的能力就是 get/setDemand 和 注册/解绑监听接口。

主用户IBinder死亡,开始启动访客模式SystemUI.这里就是开启了另外一个AIDL,等会儿讲.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Only for secondary users, this is the death handler for the binder from the system user
private final IBinder.DeathRecipient mUserToSystemCallbacksDeathRcpt = new IBinder.DeathRecipient() {
@Override
public void binderDied() {
mUserToSystemCallbacks = null;
EventLog.writeEvent(EventLogTags.SYSUI_RECENTS_CONNECTION,
EventLogConstants.SYSUI_RECENTS_CONNECTION_USER_SYSTEM_UNBOUND,
sSystemServicesProxy.getProcessUser());

// Retry after a fixed duration
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
registerWithSystemUser();
}
}, BIND_TO_SYSTEM_USER_RETRY_DELAY);
}
};

接口定义:

frameworks/base/packages/SystemUI/src/com/android/systemui/recents/IRecentsSystemUserCallbacks.aidl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.android.systemui.recents;

import android.graphics.Rect;

/**
* Due to the fact that RecentsActivity is per-user, we need to establish an
* interface (this) for the non-system user to register itself for callbacks and to
* callback to the system user to update internal state.
*/
oneway interface IRecentsSystemUserCallbacks {
void registerNonSystemUserCallbacks(IBinder nonSystemUserCallbacks, int userId);

void updateRecentsVisibility(boolean visible);
void startScreenPinning(int taskId);
void sendRecentsDrawnEvent();
void sendDockingTopTaskEvent(int dragMode, in Rect initialRect);
void sendLaunchRecentsEvent();
void setWaitingForTransitionStartEvent(boolean waitingForTransitionStart);
}

接口中间件

out/target/common/obj/APPS/SystemUI_intermediates/src/com/android/systemui/recents/IRecentsSystemUserCallbacks.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
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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
/*
* This file is auto-generated. DO NOT MODIFY.
* Original file: frameworks/base/packages/SystemUI/src/com/android/systemui/recents/IRecentsSystemUserCallbacks.aidl
*/
package com.android.systemui.recents;
/**
* Due to the fact that RecentsActivity is per-user, we need to establish an
* interface (this) for the non-system user to register itself for callbacks and to
* callback to the system user to update internal state.
*/
public interface IRecentsSystemUserCallbacks extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements com.android.systemui.recents.IRecentsSystemUserCallbacks
{
private static final java.lang.String DESCRIPTOR = "com.android.systemui.recents.IRecentsSystemUserCallbacks";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an com.android.systemui.recents.IRecentsSystemUserCallbacks interface,
* generating a proxy if needed.
*/
public static com.android.systemui.recents.IRecentsSystemUserCallbacks asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.android.systemui.recents.IRecentsSystemUserCallbacks))) {
return ((com.android.systemui.recents.IRecentsSystemUserCallbacks)iin);
}
return new com.android.systemui.recents.IRecentsSystemUserCallbacks.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
{
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_registerNonSystemUserCallbacks:
{
data.enforceInterface(DESCRIPTOR);
android.os.IBinder _arg0;
_arg0 = data.readStrongBinder();
int _arg1;
_arg1 = data.readInt();
this.registerNonSystemUserCallbacks(_arg0, _arg1);
return true;
}
case TRANSACTION_updateRecentsVisibility:
{
data.enforceInterface(DESCRIPTOR);
boolean _arg0;
_arg0 = (0!=data.readInt());
this.updateRecentsVisibility(_arg0);
return true;
}
case TRANSACTION_startScreenPinning:
{
data.enforceInterface(DESCRIPTOR);
int _arg0;
_arg0 = data.readInt();
this.startScreenPinning(_arg0);
return true;
}
case TRANSACTION_sendRecentsDrawnEvent:
{
data.enforceInterface(DESCRIPTOR);
this.sendRecentsDrawnEvent();
return true;
}
case TRANSACTION_sendDockingTopTaskEvent:
{
data.enforceInterface(DESCRIPTOR);
int _arg0;
_arg0 = data.readInt();
android.graphics.Rect _arg1;
if ((0!=data.readInt())) {
_arg1 = android.graphics.Rect.CREATOR.createFromParcel(data);
}
else {
_arg1 = null;
}
this.sendDockingTopTaskEvent(_arg0, _arg1);
return true;
}
case TRANSACTION_sendLaunchRecentsEvent:
{
data.enforceInterface(DESCRIPTOR);
this.sendLaunchRecentsEvent();
return true;
}
case TRANSACTION_setWaitingForTransitionStartEvent:
{
data.enforceInterface(DESCRIPTOR);
boolean _arg0;
_arg0 = (0!=data.readInt());
this.setWaitingForTransitionStartEvent(_arg0);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}

private static class Proxy implements com.android.systemui.recents.IRecentsSystemUserCallbacks
{
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 registerNonSystemUserCallbacks(android.os.IBinder nonSystemUserCallbacks, int userId) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeStrongBinder(nonSystemUserCallbacks);
_data.writeInt(userId);
mRemote.transact(Stub.TRANSACTION_registerNonSystemUserCallbacks, _data, null, android.os.IBinder.FLAG_ONEWAY);
}
finally {
_data.recycle();
}
}

@Override public void updateRecentsVisibility(boolean visible) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(((visible)?(1):(0)));
mRemote.transact(Stub.TRANSACTION_updateRecentsVisibility, _data, null, android.os.IBinder.FLAG_ONEWAY);
}
finally {
_data.recycle();
}
}

@Override public void startScreenPinning(int taskId) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(taskId);
mRemote.transact(Stub.TRANSACTION_startScreenPinning, _data, null, android.os.IBinder.FLAG_ONEWAY);
}
finally {
_data.recycle();
}
}

@Override public void sendRecentsDrawnEvent() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_sendRecentsDrawnEvent, _data, null, android.os.IBinder.FLAG_ONEWAY);
}
finally {
_data.recycle();
}
}

@Override public void sendDockingTopTaskEvent(int dragMode, android.graphics.Rect initialRect) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(dragMode);
if ((initialRect!=null)) {
_data.writeInt(1);
initialRect.writeToParcel(_data, 0);
}
else {
_data.writeInt(0);
}
mRemote.transact(Stub.TRANSACTION_sendDockingTopTaskEvent, _data, null, android.os.IBinder.FLAG_ONEWAY);
}
finally {
_data.recycle();
}
}

@Override public void sendLaunchRecentsEvent() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_sendLaunchRecentsEvent, _data, null, android.os.IBinder.FLAG_ONEWAY);
}
finally {
_data.recycle();
}
}

@Override public void setWaitingForTransitionStartEvent(boolean waitingForTransitionStart) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(((waitingForTransitionStart)?(1):(0)));
mRemote.transact(Stub.TRANSACTION_setWaitingForTransitionStartEvent, _data, null, android.os.IBinder.FLAG_ONEWAY);
}
finally {
_data.recycle();
}
}
}

static final int TRANSACTION_registerNonSystemUserCallbacks = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_updateRecentsVisibility = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
static final int TRANSACTION_startScreenPinning = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
static final int TRANSACTION_sendRecentsDrawnEvent = (android.os.IBinder.FIRST_CALL_TRANSACTION + 3);
static final int TRANSACTION_sendDockingTopTaskEvent = (android.os.IBinder.FIRST_CALL_TRANSACTION + 4);
static final int TRANSACTION_sendLaunchRecentsEvent = (android.os.IBinder.FIRST_CALL_TRANSACTION + 5);
static final int TRANSACTION_setWaitingForTransitionStartEvent = (android.os.IBinder.FIRST_CALL_TRANSACTION + 6);
}
public void registerNonSystemUserCallbacks(android.os.IBinder nonSystemUserCallbacks, int userId) throws android.os.RemoteException;
public void updateRecentsVisibility(boolean visible) throws android.os.RemoteException;
public void startScreenPinning(int taskId) throws android.os.RemoteException;
public void sendRecentsDrawnEvent() throws android.os.RemoteException;
public void sendDockingTopTaskEvent(int dragMode, android.graphics.Rect initialRect) throws android.os.RemoteException;
public void sendLaunchRecentsEvent() throws android.os.RemoteException;
public void setWaitingForTransitionStartEvent(boolean waitingForTransitionStart) throws android.os.RemoteException;
}

接口的实现

frameworks/base/packages/SystemUI/src/com/android/systemui/recents/RecentsSystemUser.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
95
96
97
98
99
package com.android.systemui.recents;

import android.content.Context;
import android.graphics.Rect;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.EventLog;
import android.util.Log;
import android.util.SparseArray;

import com.android.systemui.EventLogConstants;
import com.android.systemui.EventLogTags;
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.activity.DockedTopTaskEvent;
import com.android.systemui.recents.events.activity.RecentsActivityStartingEvent;
import com.android.systemui.recents.events.component.SetWaitingForTransitionStartEvent;
import com.android.systemui.recents.events.ui.RecentsDrawnEvent;
import com.android.systemui.recents.misc.ForegroundThread;

/**
* An implementation of the system user's Recents interface to be called remotely by secondary
* users.
*/
public class RecentsSystemUser extends IRecentsSystemUserCallbacks.Stub {

private static final String TAG = "RecentsSystemUser";

private Context mContext;
private RecentsImpl mImpl;
private final SparseArray<IRecentsNonSystemUserCallbacks> mNonSystemUserRecents =
new SparseArray<>();

public RecentsSystemUser(Context context, RecentsImpl impl) {
mContext = context;
mImpl = impl;
}

@Override
public void registerNonSystemUserCallbacks(final IBinder nonSystemUserCallbacks,
final int userId) {
try {
final IRecentsNonSystemUserCallbacks callback =
IRecentsNonSystemUserCallbacks.Stub.asInterface(nonSystemUserCallbacks);
nonSystemUserCallbacks.linkToDeath(new IBinder.DeathRecipient() {
@Override
public void binderDied() {
mNonSystemUserRecents.removeAt(mNonSystemUserRecents.indexOfValue(callback));
EventLog.writeEvent(EventLogTags.SYSUI_RECENTS_CONNECTION,
EventLogConstants.SYSUI_RECENTS_CONNECTION_SYSTEM_UNREGISTER_USER,
userId);
}
}, 0);
mNonSystemUserRecents.put(userId, callback);
EventLog.writeEvent(EventLogTags.SYSUI_RECENTS_CONNECTION,
EventLogConstants.SYSUI_RECENTS_CONNECTION_SYSTEM_REGISTER_USER, userId);
} catch (RemoteException e) {
Log.e(TAG, "Failed to register NonSystemUserCallbacks", e);
}
}

public IRecentsNonSystemUserCallbacks getNonSystemUserRecentsForUser(int userId) {
return mNonSystemUserRecents.get(userId);
}

@Override
public void updateRecentsVisibility(boolean visible) {
ForegroundThread.getHandler().post(() -> {
mImpl.onVisibilityChanged(mContext, visible);
});
}

@Override
public void startScreenPinning(int taskId) {
ForegroundThread.getHandler().post(() -> {
mImpl.onStartScreenPinning(mContext, taskId);
});
}

@Override
public void sendRecentsDrawnEvent() {
EventBus.getDefault().post(new RecentsDrawnEvent());
}

@Override
public void sendDockingTopTaskEvent(int dragMode, Rect initialRect) throws RemoteException {
EventBus.getDefault().post(new DockedTopTaskEvent(dragMode, initialRect));
}

@Override
public void sendLaunchRecentsEvent() throws RemoteException {
EventBus.getDefault().post(new RecentsActivityStartingEvent());
}

@Override
public void setWaitingForTransitionStartEvent(boolean waitingForTransitionStart) {
EventBus.getDefault().post(new SetWaitingForTransitionStartEvent(
waitingForTransitionStart));
}
}

1) 接口定义: frameworks/base/packages/SystemUI/src/com/android/systemui/recents/IRecentsNonSystemUserCallbacks.aidl
2)编译中间件:
3)接口实现:frameworks/base/packages/SystemUI/src/com/android/systemui/recents/RecentsImplProxy.java
4)接口使用:

Q:很好奇AIDL文件写好后是如何编译成java文件的?
待后续继续研究.

参考资料

Android 深入浅出AIDL(一)
Android 深入浅出AIDL(二)

Android:学习AIDL,这一篇文章就够了(上)
Android:学习AIDL,这一篇文章就够了(下)

android 最近任务多进程调度逻辑分析

带你一起剖析Android AIDL跨进程通信的实现原理

实例
Android基础进阶之学习使用AIDL进行跨进程通信
Android进阶之AIDL的使用详解(一)

三步掌握 Android 中的 AIDL

android AIDL在编译中运行的过程

Android进程通讯——AIDL