首先各种Token都是Binder对象,Binder对象一般有两种用途,一是方便进程之间的跨进程通信,另一种是用于跨进程标识同一对象;token更重要的作用是后者;
AMS Token:
在AMS端创建一个Activity时会创建一个ActivityRecord作为该Activity的映像,其中会新建一个IApplicationToken.Stub类型的appToken,它向WMS提供了如下方法用来通知AMS关于window的消息:(以下简称AMS token)
(1)AMS Token创建:
第一次启动Activity,在AMS端创建ActivityRecord时会new一个token放在ActivityRecord中作为成员变量;
class ActivityStarter {
private int startActivity(.....) {
...
ActivityRecord r = new ActivityRecord(mService,...);
}
}
//创建ActivityRecord的时候还会new一个apptoken,这个token在AMS端和Client端都是Acitvity的唯一标识
ActivityRecord(...) {
appToken = new Token(this);
...
}
(2)AMS调用WMS的addAppToken接口,给WMS添加新建Activity的映像;
AMS端:把AppToken传递给WMS:
//className = ActivityStack
final void startActivityLocked(ActivityRecord r, ...) {
mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken, ...);
}
WMS端:
WMS中有一个Map
class WindowManagerService {
//这个map的键就是AppToken
HashMap<IBinder,AppWindowToken> mTokenMap;
public void addAppToken(IApplicationToken token, ...) {
......
synchronized(mWindowMap) {
AppWindowToken atoken = findAppWindowToken(token.asBinder());
if (atoken != null) {
return;
}
//一个AppToken对应一个AppWindowToken
//需要为没有AppWindowToken的Activity需要新建AppWindowToken
atoken = new AppWindowToken(this, token, voiceInteraction);
mTokenMap.put(token.asBinder(), atoken);
}
}
}
(3)将token传递到Client进程:
AMS端:用ApplicationThread将binder传递给Client进程:
final boolean realStartActivityLocked(ActivityRecord r, ...) {
app.thread.scheduleLaunchActivity(r.appToken, ...);
}
Client端:建立一个Activity在Client端的映像:
public final void scheduleLaunchActivity(IBinder token, ...) {
ActivityClientRecord r = new ActivityClientRecord();
r.token = token;
...
sendMessage(H.LAUNCH_ACTIVITY, r);
}
(4)添加窗口:
Client端:
public void setView(View view, WindowManager.LayoutParams attrs, ...) {
...
//mWindow是W类型,提供了Client端向WMS开放的服务;
//attrs中包含了AMS Token
res = mWindowSession.addToDisplay(session, mWindow, attrs, ...) ;
}
WMS端:根据AMS Token(可唯一映射到一个Activity)为依附于该Activity的Window建立Window在WMS端的唯一描述符;
final HashMap<IBinder, WindowToken> mTokenMap = new HashMap<>();
public int addWindow(Session session, IWindow client, WindowManager.LayoutParams attrs, ...) {
......
boolean addToken = false;
//可见mTokenMap 的key值为AMS Binder
WindowToken token = mTokenMap.get(attrs.token);
......
win = new WindowState(this, session, client, token,
attachedWindow, appOp[0], seq, attrs, viewVisibility, displayContent);
mWindowMap.put(client.asBinder(), win);
....
}
总结:
Activity中的token: 以上这个类的代理对象就是Activity中的token,每个Acvitity都对应这样一个token,并在Activity执行attach时赋值;同时在attach方法中,系统会创建Activity所属的Window;
Window中的token: 当Window对应一个Activity时其中的token就是Activity的token;当Window对应一个Dialog或系统弹框,这时token就为空;
WindowManager.LayoutParams中的token: 当LayoutParams对应的是Activity时token就是AMS token,一个AMS token又会对应一个WindowToken,这个Activity中的所有Window都会共享这一个WindowToken
WMS的Token:
WindowToken和AppWindowToken:父子类关系,WindowToken为父类;
每个Window都对应一个WindowToken,但只有Activity类型的Window才会有AppWindowToken;
AppWindowToken会持有AMS token的引用;
WMS中有一个Map
AMS Token:
向WMS提供回调以便窗口发生变化时AMS做出相应的配合
interface IApplicationToken extends IApplicationToken.Stub { //(Binder)
private final ActivityManagerService mService;
void windowsDrawn();
void windowsVisible();
void windowsGone();
boolean keyDispatchingTimedOut(String reason);
long getKeyDispatchingTimeout();
}
WindowToken:
class WindowToken {
final WindowManagerService service;
// The actual token.
final IBinder token;
final int windowType;
AppWindowToken appWindowToken;
// All of the windows associated with this token.
final WindowList windows = new WindowList();
WindowToken(WindowManagerService _service, IBinder _token, int type, boolean _explicit)
void removeAllWindows()
}
AppWindowToken
class AppWindowToken extends WindowToken {
}