Android 7.1 GUI系统-窗口管理WindowManagerService(一)

一,WindowManagerService窗口管理员。

什么是窗口?直观的看是一个界面,比如桌面,比如打开的一张照片。

SurfaceFlinger的角度看,它是一个layer,当向surfaceflinger申请一个surface时,实际是创建了一个layer,承载着跟窗口有关的数据。

WindowManagerService的角度看,它是windowState,管理着窗口有关的状态。

WindowManagerService除了管理着系统中所有的窗口外,还有一个重要功能就是负责事件的分发。因为它管理着系统的所有窗口,所以当有一个事件到来时,WMS最有可能直到那个窗口适合处理这个事件。

1WindowManagerService的启动。

WMS是由systemServer启动的系统服务的一种。

	private void startOtherServices() @SystemServer.java{
		WindowManagerService wm = null;
		InputManagerService inputManager = null;
//先实例化一个InputManagerService对象,作为WindowManagerService 的参数,InputManagerService负责事件的接收分发。
		inputManager = new InputManagerService(context);
		wm = WindowManagerService.main(context, inputManager,
			mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,!mFirstBoot, mOnlyCore);
//注册到ServiceManager中。
		ServiceManager.addService(Context.WINDOW_SERVICE, wm);
		ServiceManager.addService(Context.INPUT_SERVICE, inputManager);
	}	

//WindowManagerService是在一个单独的线程中运行的,而且是以同步(runWithScissors)的方式启动的这个线程,所以在WindowManagerService启动完成之后,SystemServer才能继续往下走。

public static WindowManagerService main(final Context context,final InputManagerService im,
	final boolean haveInputMethods, final boolean showBootMsgs,final boolean onlyCore) @WindowManagerService.java{
	final WindowManagerService[] holder = new WindowManagerService[1];
	DisplayThread.getHandler().runWithScissors(new Runnable() {
		@Override
		public void run() {
			holder[0] = new WindowManagerService(context, im,haveInputMethods, showBootMsgs, onlyCore);
		}
	}, 0);
	return holder[0];
}

在最新的android版本中,使用lambda表达式,来实现Runnable接口这个匿名内部类:

    public static WindowManagerService main(final Context context, final InputManagerService im,
            final boolean haveInputMethods, final boolean showBootMsgs, final boolean onlyCore,
            WindowManagerPolicy policy) {
        DisplayThread.getHandler().runWithScissors(() ->
                sInstance = new WindowManagerService(context, im, haveInputMethods, showBootMsgs,
                        onlyCore, policy), 0);
        return sInstance;
    }

() -> {}代替了整个匿名内部了Runnable,写法非常简洁。如果run()方法有多行代码就用{}括起来,如果只有一行代码可以省略大括号,如:sInstance = new WindowManagerService(context, im, haveInputMethods, showBootMsgs,

                        onlyCore, policy),

WMS所在的线程就是DisplayThread这个显示线程,这个线程不仅被WMS使用,DisplayManagerServiceInputManagerService也会使用。当实例化WindowManagerService时,它的成员变量mH就与DisplayThread产生了关联,后期可以通过mH这个handler投递事件到DisplayThreadlooper队列中。mHWMS的内部类finalclass H extends Handler {}

2)应用程序、WMSAMS之间的关系。

应用程序的启动,通常是Activity的启动,因为Activity是主要用于UI显示的组件,所以必然跟WMS产生关联。

a)ActivityAMS,或者说应用进程到AMS是通过IActivityManager来通信的,在应用的主线程中,会通过:

IActivityManagermgr =ActivityManagerNative.getDefault();获取AMS的服务句柄,在应用进程启动完成,回调通知AMS时,会通过mgr.attachApplication(mAppThread);传入一个参数mAppThread,类型是ApplicationThread,所以ApplicationThread就是AMS访问应用进程的一个桥梁,这个过程是跨进程的。

startActivity的过程中,AMS会生成一个ActivityRecord对象来记录这个Activity

b),应用程序到WMS,是通过IWindowSession这个接口,ViewRootImpl的构造时,会实例化对象mWindowSession

IWindowSessionmWindowSession =WindowManagerGlobal.getWindowSession();ViewRootImpl是应用程序中View树的管理者,要获取WMS的服务都是通过mWindowSession这个接口来实现,比如申请window

在通过mWindowSession.addToDisplay(mWindow,…..);申请window时,传入参数mWindow,类型是W

ViewRootImpl的内部类,staticclass W extends IWindow.Stub {},这个mWindowWMS访问应用进程的接口。

每个应用程序的窗口在WMS中都有一个WindowState实例相对应。

c),前面提到接口多数是基于AIDL实现的BinderServer,用于应用进程跟系统进程间跨进程交互。

WMSAMS都在SystemServer进程,是可以直接进行函数调用的,比如在SystemServer.java中:

private void startOtherServices() @SystemServer.java{
	mActivityManagerService.setWindowManager(wm);
}

AMS通过setWindowManagerWMS的句柄wm设置给了AMS中的成员mWindowManager

WMS中有一个AppWindowToken对应了AMS中的ActivityRecord,这个AppWindowToken是在startActivity的过程中添加的,具体是通过调用mWindowManager.addAppToken(…)实现的。


d)在把一个窗口通过addView注册到WMS后,wms会请surfaceflinger申请一个surface承载UI数据,使窗口内容可以显示到屏幕上。窗口的拥有者通过WindowManagerImpl.java,进一步通过WindowManagerGlobal.java管理名下所有的窗口,具体就是mViews,mRoots,mParams三个列表。

    原文作者:lin-0410
    原文地址: https://blog.csdn.net/lin20044140410/article/details/78735793
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞