客户端:
- ActivityThread
- ViewRootImpl
服务端:
- WindowManagerService
- ActivityManagerService
相关通信:
- IWindowSession
- IWindow
- APP端窗口暴露给WMS的抽象实例,在ViewRootImpl中实例化,与ViewRootImpl一一对应,同时也是WMS向APP端发送消息的Binder通道。
- WindowToken:
- 窗口的令牌,其实也可以看做窗口分组的依据,在WMS端,与分组对应的数据结构是WindowToken(窗口令牌),而与组内每个窗口对应的是WindowState对象,每块令牌(AppWindowToken、WindowToken)都对应一组窗口(WindowState),Activity与Dialog对应的是AppWindowToken,PopupWindow对应的是普通的WindowToken。
- WindowState:
- WMS端窗口的令牌,与IWindow,或者说与窗口一一对应,是WMS管理窗口的重要依据。
- AppToken:
- 其实是ActivityRecord里面的IApplicationToken.Stub appToken 代理,也是ActivityClientRecord里面的token,可以看做Activity在其他服务(非AMS)的抽象
AMS和WMS通信:
- Activity组件在AMS和WMS之间的连接是通过AppWindowToken描述的。
- AppWindowToken是WindowToken的子类。WindowToken标识一个窗口。如果是Activity组件窗口,则是APPWindowToken的实现。
- WindowToken内部的appWindowToken成员:如果为Null,则不是Activity组件窗口;否则就不为Null
- WindowToken内部的token成员:就是ActivityRecord中的IApplicationToken成员,这个IapplicationToken的实现是一个Token内部类,在ActivityRecord中。它包含了ActivityRecord类的弱引用本身以及AMS对象。可以说这个token成员在WMS这边就相当于ActivityRecord本身。
- 每一个Activity组件,在AMS中都保存着一个ActivityRecord。
- 建立通信过程如下:
- AMS中,调用到ActivityStack内部的addConfigOverride()函数时,会将ActivityRecord中的appToken(IApplicationToken)成员交给WMS,用于创建AppWindowToken
- 此时在WMS中,AppWindowToken被创建,ActivityRecord中的appToken就被存放在了AppWindowToken内部的token成员中。
- 随后,WMS中的mTokenMap集合发挥作用。将AppWindowToken中的token成员作为key,AppWindowToken本身作为值,存储到TokenMap中。
- TokenMap保存的是一系列的WindowToken对象,每一个WindowToken对象都是用来描述一个窗口。
客户端和WMS通信:
- IWindowSession
- 在创建ViewRootImpl时,构造器中会调用WindowManagerGlobal.getWindowSession()。此函数会和WMS通信,创建一个Session对象。这个就是IWindowSession的实现。这个Binder存放在ViewRootImpl中,用于客户端与WMS通信。
- IWindowSession中的实现如下:
int add(IWindow window, int seq, in WindowManager.LayoutParams attrs,
in int viewVisibility, out Rect outContentInsets, out Rect outStableInsets,
out InputChannel outInputChannel);
int addToDisplay(IWindow window, int seq, in WindowManager.LayoutParams attrs,
in int viewVisibility, in int layerStackId, out Rect outContentInsets,
out Rect outStableInsets, out Rect outOutsets, out InputChannel outInputChannel);
int addWithoutInputChannel(IWindow window, int seq, in WindowManager.LayoutParams attrs,
in int viewVisibility, out Rect outContentInsets, out Rect outStableInsets);
int addToDisplayWithoutInputChannel(IWindow window, int seq, in WindowManager.LayoutParams attrs,
in int viewVisibility, in int layerStackId, out Rect outContentInsets,
out Rect outStableInsets);
void remove(IWindow window);
- 由上面可知,IwindowSession主要可以让客户端通知WMS增加或者删除窗口显示
WMS和客户端通信:
- ViewRootImpl创建之后,会通知WMS显示窗口,但是此时,还需要将客户端的一个唯一标示,交给服务端,好方便WMS和客户端进行通信。
- 这个东西,就是IWindow
- ViewRootImpl的setView()函数中,客户端使用IWindowSession通知WMS显示窗口。调用的是addToDisplay()函数。该函数中,传入了IWindow这个binder,随后在WMS中,WMS拿着IWindow创建了这个Activity对应的WindowState。将IWindow保存在WindowState中,便于后续和客户端通信。
- IWindow的实现:
void executeCommand(String command, String parameters, in ParcelFileDescriptor descriptor);
void resized(in Rect frame, in Rect overscanInsets, in Rect contentInsets,
in Rect visibleInsets, in Rect stableInsets, in Rect outsets, boolean reportDraw,
in Configuration newConfig, in Rect backDropFrame, boolean forceLayout,
boolean alwaysConsumeNavBar);
void moved(int newX, int newY);
void dispatchAppVisibility(boolean visible);
void dispatchGetNewSurface();
/**
,* Tell the window that it is either gaining or losing focus. Keep it up
,* to date on the current state showing navigational focus (touch mode) too.
,*/
void windowFocusChanged(boolean hasFocus, boolean inTouchMode);
void closeSystemDialogs(String reason);
/**
,* Called for wallpaper windows when their offsets change.
,*/
void dispatchWallpaperOffsets(float x, float y, float xStep, float yStep, boolean sync);
void dispatchWallpaperCommand(String action, int x, int y,
int z, in Bundle extras, boolean sync);
/**
,* Drag/drop events
,*/
void dispatchDragEvent(in DragEvent event);
/**
,* Pointer icon events
,*/
void updatePointerIcon(float x, float y);
/**
,* System chrome visibility changes
,*/
void dispatchSystemUiVisibilityChanged(int seq, int globalVisibility,
int localValue, int localChanges);
/**
,* Called for non-application windows when the enter animation has completed.
,*/
void dispatchWindowShown();
/**
,* Called when Keyboard Shortcuts are requested for the window.
,*/
void requestAppKeyboardShortcuts(IResultReceiver receiver, int deviceId);
- WindowState的相关数据:
- mClient:指向一个实现了IWindow接口的Binder代理对象,它引用了运行在应用程序进程这一侧的一个类型为W的Binder本地对象,通过它可以与客户端的Activity组件进行通信。
- WindowManagerService中:
- WindowMap存放着IWindow为key,WindowState为value的数据。