Android Framework 窗口子系统 (01)WindowMangerService基础知识
1. WMS的启动流程
- WMS的启动主要涉及3个线程:system_server、android.display、android.ui;其中WMS.H.handleMessage 运行在android.display线程中。
- WMS中3个关键步骤:创建WMS对象,初始化显示信息,处理systemready通知
1.1 WMS关键成员变量说明
1.2 重要成员变量说明
你的
- mTokenMap,HashMap,保存所有显示令牌(类型为WindowToken),一个窗口必须隶属于某一个显示令牌。衍生变量还有:
mAppTokens,保存了所有属于Activity的显示令牌(WindowToken的子类AppWindowToken),mAppTokens列表是有序的,
它与AMS中的mHistory列表的顺序保持一致,反映了系统中Activity的顺序。 mExitingTokens,保存了正在退出过程中的显示令牌等。
- mWindowMap,HashMap,保存所有窗口的状态信息(类型为WindowState),衍生变量还有:
mPendingRemove,保存了那些退出动画播放完成并即将被移除的窗口 mLosingFocus,保存了那些失去了输入焦点的窗口。 在DisplayContent中,也有一个windows列表,这个列表存储了显示在此DisplayContent中的窗口,并且它是有序的。窗口在这个列表中的位置决定了其最终显示时的Z序。
mSessions,List,这个列表保存了当前所有想向WMS寻求窗口管理服务的客户端。注意Session是具有进程唯一性。
1.3 窗口类型定义
WMS中定义了3类窗口,应用窗口,子窗口和系统窗口,分别对这3种窗口进行说明,该图列举了几种常见的窗口,如下所示:
这里涉及几类窗口:
- 应用程序窗口 (Application Window): 包括所有应用程序自己创建的窗口,以及在应用起来之前系统负责显示的窗口。
- 子窗口(Sub Window):比如应用自定义的对话框,或者输入法窗口,子窗口必须依附于某个应用窗口(设置相同的token)。
- 系统窗口(System Window): 系统设计,不依附于任何应用窗口,比如:状态栏(Status Bar)、导航栏(Navigation Bar)、壁纸(Wallpaper)、来电显示窗口(Phone)、锁屏窗口(KeyGuard)、信息提示窗口(Toast)、音量调整窗口、鼠标光标等等。
2.应用进程和WMS之间的关系
-
Activity中mWindow是PhoneWindow类型的,PhoneWindow是继承Window的。
-
Activity中mWindowManager是WindowManagerImpl类型的,WindowManagerImpl实现了WindowManager接口
2.1 建立应用与WMS之间的关系,WMS与应用之间的关系
-
ViewRootImpl有很多成员变量,与WMS相关的几个变量如下:
public final class ViewRootImpl implements ViewParent, View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks {
... final IWindowSession mWindowSession;
final W mWindow; final Surface mSurface = new Surface();
final View.AttachInfo mAttachInfo; ...
} 它的构造方法对这几个关键变量进行初始化,代码如下所示 public ViewRootImpl(Context context, Display display) {
mContext = context;
mWindowSession = WindowManagerGlobal.getWindowSession();//关键点1,建立和WindowManagerService的关系
...
mWindow = new W(this);//关键点2,mWindow是一个W类型,注意它不是Window类型,而是IWindow类型 ...
mAttachInfo = new View.AttachInfo(mWindowSession, mWindow, display, this, mHandler, this);
...
}
这里的mWindowSession是IWindowSession类型,它是WMS中某个Binder对象的引用对象,继续分析getWindowsession函数,代码如下:
public static IWindowSession getWindowSession() {
synchronized (WindowManagerGlobal.class) {
if (sWindowSession == null) {
try {
InputMethodManager imm = InputMethodManager.getInstance(); //下面这个函数先得到WindowManagerService的Binder代理
IWindowManager windowManager = getWindowManagerService(); //调用代理端的openSession
sWindowSession = windowManager.openSession( new IWindowSessionCallback.Stub() {
@Override public void onAnimatorScaleChanged(float scale) {
ValueAnimator.setDurationScale(scale);
}
},
imm.getClient(), imm.getInputContext());
} catch (RemoteException e) {
Log.e(TAG, "Failed to open window session", e);
}
}
return sWindowSession;
}
}
-
Activity的创建流程后面有一个handleResumeActivity方法,方法实现如下:
final void handleResumeActivity(IBinder token,boolean clearHide, boolean isForward, boolean reallyResume) {
unscheduleGcIdler();
...
r.activity.makeVisible();
//这里仅关注此方法
...
}
继续分析makeVisible,代码如下:
void makeVisible() {
if (!mWindowAdded) {
ViewManager wm = getWindowManager();
wm.addView(mDecor, getWindow().getAttributes());//关键是这句代码
mWindowAdded = true;
}
/// M: BMW @{
MultiWindowProxy mMultiWindowProxy = MultiWindowProxy.getInstance();
if (MultiWindowProxy.isFeatureSupport() && mMultiWindowProxy != null) {
mMultiWindowProxy.setFloatDecorVisibility(mToken, View.VISIBLE); }
/// @} mDecor.setVisibility(View.VISIBLE); }
这里又调用了WM的addView方法,参数是mDecor,这里实际上调用的是WindowManagerGlobal(WM->WMImpl->WMG流程),代码如下:
public void addView(View view, ViewGroup.LayoutParams params, Display display, Window parentWindow) {
...
//参数检查
ViewRootImpl root;
View panelParentView = null;
synchronized (mLock) {
...
root = new ViewRootImpl(view.getContext(), display);
view.setLayoutParams(wparams);
//加入View、ViewRootImpl、LayoutParams 3个对象到列表
mViews.add(view); mRoots.add(root);
mParams.add(wparams);
}
... root.setView(view, wparams, panelParentView); ...}
注意:这里最重要的一点:创建ViewRootImpl对象,通过setView方法把它和顶层View关联在一起 这里着重分析setView方法,代码如下:
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
synchronized (this) {
if (mView == null) {
//ViewRootImpl与View的关联只能做一次,如果赋值过吗,就不会再执行
mView = view;//将顶层视图DecorView赋值给全局的mView
...
try {
mOrigWindowType = mWindowAttributes.type;
mAttachInfo.mRecomputeGlobalAttributes = true;
collectViewAttributes();
//调用IWindowSession的add函数,第一个参数是mWindow,它的类型是W,ViewRootImpl中的内部类
res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes, getHostVisibility(), mDisplay.getDisplayId(), mAttachInfo.mContentInsets, mAttachInfo.mStableInsets, mInputChannel);
} catch (RemoteException e) { ... } ... } } }
特殊说明:
W是ViewRootImpl中的静态内部类,是一个Binder服务类通过addToDisplay方法将mWindow实例传输到WMS中, W在WMS中的引用对象类型是IWindow,WMS保存了应用中每个顶层窗口的IWindow对象。 W的关键代码如下:
static class W extends IWindow.Stub {
private final WeakReference mViewAncestor;
private final IWindowSession mWindowSession;
}
-
建立WMS与应用之间的关系
在WMS中,WindowState对象代表一个窗口,WS中定义了大量成员变量表示窗口信息,看关键的2个变量:
final class WindowState implements WindowManagerPolicy.WindowState {
static final String TAG = "WindowState";
...
final Session mSession; //WMS为客户进程创建的Binder服务对象 final IWindow mClient; //客户端进程Binder对象,W的引用对象
... }
-
installDecor的功能:主要是创建DecorView和它的下级Layout,根据需要创建ActionBar。当installDecor执行完,Activity的框架View就都创建出来了,DecorView的定义在PhoneWindow中,是它的一个内部类,代码如下: private final class DecorView extends FrameLayout implements RootViewSurfaceTaker {
...
} DecorView继承了FrameLayout ,并且实现了RootViewSurfaceTaker 接口,是Activity中View树的根。