一,WindowManagerService窗口管理员。
什么是窗口?直观的看是一个界面,比如桌面,比如打开的一张照片。
从SurfaceFlinger的角度看,它是一个layer,当向surfaceflinger申请一个surface时,实际是创建了一个layer,承载着跟窗口有关的数据。
从WindowManagerService的角度看,它是windowState,管理着窗口有关的状态。
WindowManagerService除了管理着系统中所有的窗口外,还有一个重要功能就是负责事件的分发。因为它管理着系统的所有窗口,所以当有一个事件到来时,WMS最有可能直到那个窗口适合处理这个事件。
1)WindowManagerService的启动。
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使用,DisplayManagerService、InputManagerService也会使用。当实例化WindowManagerService时,它的成员变量mH就与DisplayThread产生了关联,后期可以通过mH这个handler投递事件到DisplayThread的looper队列中。mH是WMS的内部类finalclass H extends Handler {}。
2)应用程序、WMS、AMS之间的关系。
应用程序的启动,通常是Activity的启动,因为Activity是主要用于UI显示的组件,所以必然跟WMS产生关联。
a),Activity到AMS,或者说应用进程到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 {},这个mWindow是WMS访问应用进程的接口。
每个应用程序的窗口在WMS中都有一个WindowState实例相对应。
c),前面提到接口多数是基于AIDL实现的BinderServer,用于应用进程跟系统进程间跨进程交互。
WMS和AMS都在SystemServer进程,是可以直接进行函数调用的,比如在SystemServer.java中:
private void startOtherServices() @SystemServer.java{
mActivityManagerService.setWindowManager(wm);
}
AMS通过setWindowManager把WMS的句柄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三个列表。