Android 12 addWindow过程分析

1 背景

分析过Window层级结构之后,以addWindow为切入点看一下系统是怎么使用的。而且addWindow也是系统非常重要的一个环节,无论是Activity(PhoneWindow)还是各种系统窗口,都会走到这里。

addView举例:

frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
attach方法。

2 时序分析

2.1 client端(WMS之前)

WindowManager.addView()
	WindowManagerImpl.addView()
		WindowManagerGlobal.addView()
			WindowManagerGlobal.getWindowSession()
				WindowManagerService.openSession()
					new Session()
			new ViewRootImpl()
				ViewRootImpl.setView()
					Session.addToDisplayAsUser()
  1. 如果没有创建过Session(Aidl是IWindowSession,每个进程一个),则向WMS申请创建一个Session
  2. 然后在ViewRootImpl中调用Session的 addToDisplayAsUser方法。

2.2 WMS端

Session.addToDisplayAsUser()
	WindowManagerService.addWindow()
		WindowManagerService.getDisplayContentOrCreate()
			RootWindowContainer.getWindowToken(IBinder binder)
			WindowToken.getDisplayContent()  or  RootWindowContainer.getDisplayContentOrCreate()
		new WindowToken()		// 并且设置DisplayContent(setDisplayContent())
		new WindowState()
		WindowState.attach()
			Session.windowAddedLocked()
				new SurfaceSession()
					new SurfaceComposerClient()		// jni
		WindowToken.addWindow()
			WindowToken.createSurfaceControl()
				WindowContainer.createSurfaceControl()
					WindowToken.makeSurface()
						WindowContainer.makeSurface()
							DisplayContent.makeChildSurface()
					setInitialSurfaceControlProperties()
				WindowContainer.setInitialSurfaceControlProperties()		// SurfaceControl.Builder.build()
					WindowContainer.setSurfaceControl()
					WindowContainer.updateSurfacePositionNonOrganized
		WindowManagerService.updateFocusedWindowLocked()
			RootWindowContainer.updateFocusedWindowLocked()
  1. 找到添加Window的DisplayContent
  2. 先后创建WindowToken(令牌)和WindowState(实际对象)
  3. 调用WindowState.attach()方法,内部会创建SurfaceSession,native层对应创建SurfaceComposerClient
  4. 调用WindowToken.addWindow()方法,内部创建SurfaceControl,native层对应创建SurfaceControl

3 token的传递

这里分析一下Server端怎么区分不同的client。

3.1 client创建自己的token

// ViewRootImpl.java
public final WindowManager.LayoutParams mWindowAttributes = new WindowManager.LayoutParams();

token是IBinder类型的。

以StatusBar的添加为例,ViewRootImpl中的mWindowAttributes的token就是addView的时候new的。

3.2 server中怎么使用client的token

WMS在addWindow的时候会通过token找到一个DisplayContent对象:

// 1 WMS.addWindow()中
final DisplayContent displayContent = getDisplayContentOrCreate(displayId, attrs.token);

这个寻找DisplayContent的过程如上图。

4 Session和IWindow接口

这里分析一下WMS.addWindow函数的前两个入参:

// WMS
public int addWindow(Session session, IWindow client, LayoutParams attrs, int viewVisibility,
            int displayId, int requestUserId, InsetsState requestedVisibility,
            InputChannel outInputChannel, InsetsState outInsetsState,
            InsetsSourceControl[] outActiveControls)
  • 第一个入参 Session 和client对应,一个client对应一个Session
  • 第二个入参IWindow client和client的IWindow的实现W类对应,WMS用client唯一标识一个WindowState

简单概括:addWindow时,Session负责client和Server间的通信,而IWindow参数是WindowState在client的代理。

看一下IWindow是怎么实现和初始化对象的。

// ViewRootImpl.java

final W mWindow;

public ViewRootImpl(@UiContext Context context, Display display, IWindowSession session,
        boolean useSfChoreographer) {
    mWindow = new W(this);
}

static class W extends IWindow.Stub {
    
    private final IWindowSession mWindowSession;
    
    W(ViewRootImpl viewAncestor) {
        ...
        mWindowSession = viewAncestor.mWindowSession;
    }
}

// ViewRootImpl.setView()方法中,mWindow最为参数请求Session去addWindow。
res = mWindowSession.addToDisplayAsUser(mWindow, mWindowAttributes,
                            getHostVisibility(), mDisplay.getDisplayId(), userId,
                            mInsetsController.getRequestedVisibility(), inputChannel, mTempInsets,
                            mTempControls);

posted on 2023-06-12 19:04  luke4212  阅读(220)  评论(0编辑  收藏  举报

导航