WMS窗口基础知识一

280 阅读5分钟

Android Framework 窗口子系统 (01)WindowMangerService基础知识

1. WMS的启动流程

img

  • WMS的启动主要涉及3个线程:system_server、android.display、android.ui;其中WMS.H.handleMessage 运行在android.display线程中。
  • WMS中3个关键步骤:创建WMS对象,初始化显示信息,处理systemready通知

1.1 WMS关键成员变量说明

image.png

image.png

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种窗口进行说明,该图列举了几种常见的窗口,如下所示:

image.png

这里涉及几类窗口:

  • 应用程序窗口 (Application Window): 包括所有应用程序自己创建的窗口,以及在应用起来之前系统负责显示的窗口。
  • 子窗口(Sub Window):比如应用自定义的对话框,或者输入法窗口,子窗口必须依附于某个应用窗口(设置相同的token)。
  • 系统窗口(System Window): 系统设计,不依附于任何应用窗口,比如:状态栏(Status Bar)、导航栏(Navigation Bar)、壁纸(Wallpaper)、来电显示窗口(Phone)、锁屏窗口(KeyGuard)、信息提示窗口(Toast)、音量调整窗口、鼠标光标等等。

2.应用进程和WMS之间的关系

img

  • Activity中mWindow是PhoneWindow类型的,PhoneWindow是继承Window的。

  • Activity中mWindowManager是WindowManagerImpl类型的,WindowManagerImpl实现了WindowManager接口

image.png

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树的根。