1、ViewRootImpl的数量
android中Window.java的唯一实现类是PhoneWindow.java,WindowManager.java的实现类是WindowManagerImpl.java,WindowManagerImpl.java中的WindowManagerGlobal用于具体操作View。WindowManagerGlobal.java添加View时会调用ViewRootImpl的setView(view, wparams, panelParentView, userId)方法,在setView方法中调用requestLayout()从而进行view的测量、布局和绘制工作。
WindowManagerGlobal.java中有三个集合mViews(保存DecorView)、mRoots(保存ViewRootImpl) 、mParams (保存WindowManager.LayoutParams)
WindowManagerGlobal.java
@UnsupportedAppUsage
private final ArrayList<View> mViews = new ArrayList<View>();
@UnsupportedAppUsage
private final ArrayList<ViewRootImpl> mRoots = new ArrayList<ViewRootImpl>();
@UnsupportedAppUsage
private final ArrayList<WindowManager.LayoutParams> mParams =
new ArrayList<WindowManager.LayoutParams>();
上面三个WindowManagerGlobal.java的addView方法中添加元素,addView方法是由ActivityThread.java的handleResumeActivity方法或者Activity.java的makeVisible方法调用调用。ViewRootImpl的数量等于WindowManagerGlobal.java的addView方法被调用的次数。
在Activity、Dialog、Toast显示的时候都会执行WindowManagerGlobal.addView方法。
2、requestLayout和invalidate区别
view的requestLayout()方法最终会调用到ViewRootImpl的requestLayout()方法,接着会调用scheduleTraversals() ->mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null); ->doTraversal()从而执行测量、布局和绘制。
//ViewRootImpl.java
public void requestLayout() {
if (!mHandlingLayoutInLayoutRequest) {
checkThread();
mLayoutRequested = true;
scheduleTraversals();
}
}
view的invalidate方法会调用ViewRootImpl的invalidateChildInParent方法,最终也会调用scheduleTraversals()->mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null); ->doTraversal(),区别是没有设置mLayoutRequested = true,mLayoutRequested 会影响measure步骤是否执行。
//ViewRootImpl.java
void invalidate() {
mDirty.set(0, 0, mWidth, mHeight);
if (!mWillDrawSoon) {
scheduleTraversals();
}
}
3、Window的添加
窗口就的添加最终在WMS中进行,ViewRootImpl作为应用层和WMS的桥梁。
WindowManagerGlobal.java添加View时会调用ViewRootImpl的setView(view, wparams, panelParentView, userId)方法,ViewRootImpl.setView调用Session的addToDisplay方法,Session.addToDisplay中会调用WMS的addWindow方法,该方法会创建WindowState对象,这就完成了应用层与WMS的IPC通信
//Session.java
@Override
public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets,
Rect outOutsets, InputChannel outInputChannel) {
return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,
outContentInsets, outStableInsets, outOutsets, outInputChannel);
}
4、WindowManagerImpl和WMS区别和联系
WindowManagerImpl和WMS没有直接联系,但是二者共同处理着View的添加、更新、移除、层级属性设置等操作。WindowManagerImpl在SystemServiceRegistry的静态代码模块中创建并注册(具体可以查看文章 单例模式以及在android中的使用 ),WMS在SystemServer的startOtherServices()方法中创建并注册到ServiceManager中。
//SystemServiceRegistry.java
registerService(Context.WINDOW_SERVICE, WindowManager.class,
new CachedServiceFetcher<WindowManager>() {
@Override
public WindowManager createService(ContextImpl ctx) {
return new WindowManagerImpl(ctx);
}});
//SystemServer.java
traceBeginAndSlog("StartWindowManagerService");
// WMS needs sensor service ready
ConcurrentUtils.waitForFutureNoInterrupt(mSensorServiceStart, START_SENSOR_SERVICE);
mSensorServiceStart = null;
wm = WindowManagerService.main(context, inputManager,
mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
!mFirstBoot, mOnlyCore, new PhoneWindowManager());
ServiceManager.addService(Context.WINDOW_SERVICE, wm);
ServiceManager.addService(Context.INPUT_SERVICE, inputManager);
traceEnd();
app层通过(WindowManager) context.getSystemService(Context.WINDOW_SERVICE)获取的WindowManager具体实现是WindowManagerImpl.java,具体是通过Context实现类ContextImpl.java在SystemServiceRegistry中根据名称获取已注册的服务。
//ContextImpl.java
public Object getSystemService(String name) {
return SystemServiceRegistry.getSystemService(this, name);
}
ViewRootImpl.setView方法会根据session调用到WMS中去完成实际的View操控动作,WMS中操作View会用到WindowState对象。
5、SurfaceFlinger的角色
ViewRootImpl.setView方法调用了mWindowSession.addToDisplay方法,mWindowSession.addToDisplay方法调用了WMS的addWindow方法,WMS.addWindow会创建WindowState对象,然后调用WindowState的attach方法,WindowState.attach调用mWindowSession.windowAddedLocked方法,mWindowSession.windowAddedLocked方法中就会创建SurfaceSession对象,SurfaceSession对象就是window和SurfaceFlinger 连接的桥梁。
//Session.java
void windowAddedLocked(String packageName) {
mPackageName = packageName;
mRelayoutTag = "relayoutWindow: " + mPackageName;
if (mSurfaceSession == null) {
if (WindowManagerService.localLOGV) Slog.v(
TAG_WM, "First window added to " + this + ", creating SurfaceSession");
mSurfaceSession = new SurfaceSession();
if (SHOW_TRANSACTIONS) Slog.i(
TAG_WM, " NEW SURFACE SESSION " + mSurfaceSession);
mService.mSessions.add(this);
if (mLastReportedAnimatorScale != mService.getCurrentAnimatorScale()) {
mService.dispatchNewAnimatorScaleLocked(this);
}
}
mNumWindow++;
}
一个SurfaceSession对象和创建多个surface,最后这些surface数据保存在Buffer中,上层app先从BufferQueue中申请Buffer,然后调用canvas.draw或者opengl.glDrawArrays(或者opengl.glDrawElements等函数) 去填充数据后再放入到BufferQueue中并通知SurfaceFlinger合成处理后就会显示当屏幕display上,所以SurfaceFlinger就是上层应用数据处理者(消费者),同时也是display数据的生产者。
6、display、surface、
无论开发者使用什么渲染 API,一切内容都会渲染到 Surface 上。Surface 表示缓冲区队列中的生产方,而缓冲区队列通常会被 SurfaceFlinger 消耗。在 Android 平台上创建的每个窗口都由 Surface 提供支持。所有被渲染的可见 Surface 都被 SurfaceFlinger 合成到屏幕。
下图显示了关键组件如何协同工作:
android.view包下的Display.java只是描述了显示屏的一些属性信息,具体实现在
DisplayManagerService