【framework】Surface创建流程
1 前言
View添加过程 中介绍了从 WindowManagerImpl 的 addView() 方法到 WindowState、SurfaceSession 的创建流程,本文将介绍 Surface 的创建流程。应用进程中,ViewRootImpl 持有 Surface 对象,system_server 进程中,WindowSurfaceController 持有 SurfaceControl 对象,Surface 和 SurfaceControl 都持有 native 层的同一个 Surface 对象的地址(SurfaceFlinger 进程)。
Surface 在应用进程和 system_server 进程中都有创建,因此,本文主要介绍 system_server 进程中 SurfaceControl 的创建流程和应用进程中 Surface 的创建流程。
为区分不同进程,将应用进程、system_server 进程分别标识为浅蓝色、深蓝色。
2 源码分析
2.1 ViewRootImpl 到 Session
如图,浅蓝色的类是应用进程中执行的,深蓝色的类是在 system_server 进程中执行的,黄色的类是指 AIDL 文件生成的接口(用于跨进程)。

(1)ViewRootImpl
/frameworks/base/core/java/android/view/ViewRootImpl.java
public final Surface mSurface = new Surface();
private final SurfaceControl mSurfaceControl = new SurfaceControl();
public ViewRootImpl(Context context, Display display) {
mContext = context;
//IWindowSession 类型,单例对象,getWindowSession() 方法调用 WMS 的 openSession() 方法,new 一个 Session 对象(IWindowSession.Stub 的实现类)
mWindowSession = WindowManagerGlobal.getWindowSession();
mDisplay = display;
...
mWindow = new W(this); //IWindow.Stub 的实现类
...
mAttachInfo = new View.AttachInfo(mWindowSession, mWindow, display, this, mHandler, this, context); //View.AttachInfo 类型
...
mChoreographer = Choreographer.getInstance();
mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
...
}
说明:Session 是 IWindowSession.Stub 的实现类,属于 WMS 端的类,WindowManagerGlobal.getWindowSession() 方法最终会调用 WMS 的 openSession() 方法,创建一个 Session 对象,每个应用进程,最多对应一个 Session 对象;W 类是 ViewRootImpl 的内部类,也是 IWindow.Stub 的实现类,每个 根 View 都与一个 W 一一对应,即 mWindow.asBinder() 可以作为 根 View (或窗口)的身份标识。
(2)setView
/frameworks/base/core/java/android/view/ViewRootImpl.java
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
synchronized (this) {
if (mView == null) {
mView = view;
...
mWindowAttributes.copyFrom(attrs);
...
mAttachInfo.mRootView = view;
...
if (panelParentView != null) {
mAttachInfo.mPanelParentWindowToken = panelParentView.getApplicationWindowToken();
}
...
//请求显示 View
requestLayout();
...
try {
...
//添加 View
res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes, getHostVisibility(),
mDisplay.getDisplayId(), mTmpFrame, mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
mAttachInfo.mOutsets, mAttachInfo.mDisplayCutout, mInputChannel, mTempInsets);
setFrame(mTmpFrame);
}
...
}
}
}
mWindowSession.addToDisplay() 的执行流程在 View添加过程 中已做介绍,接下来跟踪 requestLayout() 的执行流程。
(3)requestLayout
/frameworks/base/core/java/android/view/ViewRootImpl.java
public void requestLayout() {
if (!mHandlingLayoutInLayoutRequest) {
...
scheduleTraversals();
}
}
(4)scheduleTraversals
/frameworks/base/core/java/android/view/ViewRootImpl.java
void scheduleTraversals() {
if (!mTraversalScheduled) {
...
mChoreographer.postCallback(Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
...
}
}
final class TraversalRunnable implements Runnable {
public void run() {
doTraversal();
}
}
final TraversalRunnable mTraversalRunnable = new TraversalRunnable();
Choreographer 通过消息处理,最终调用 mTraversalRunnable 的 run() 方法,其中又会调用 doTraversal() 方法。
(5)doTraversal
/frameworks/base/core/java/android/view/ViewRootImpl.java
void doTraversal() {
if (mTraversalScheduled) {
...
performTraversals();
...
}
}
(6)performTraversals
/frameworks/base/core/java/android/view/ViewRootImpl.java
private void performTraversals() {
...
if (mFirst || windowShouldResize || insetsChanged || viewVisibilityChanged || params != null || mForceNextWindowRelayout) {
...
try {
...
//mWindowSession.relayout()
relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
...
}
...
}
...
if (didLayout) {
//view.requestLayout()
performLayout(lp, mWidth, mHeight);
...
}
...
if (!cancelDraw) {
...
//开始绘制:draw(fullRedrawNeeded)
performDraw();
}
...
}
(7)relayoutWindow
/frameworks/base/core/java/android/view/ViewRootImpl.java
private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility, boolean insetsPending) throws RemoteException {
...
int relayoutResult = mWindowSession.relayout(mWindow, mSeq, params, (int) (mView.getMeasuredWidth() * appScale + 0.5f),
(int) (mView.getMeasuredHeight() * appScale + 0.5f), viewVisibility, insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0,
frameNumber, mTmpFrame, mPendingOverscanInsets, mPendingContentInsets, mPendingVisibleInsets, mPendingStableInsets,
mPendingOutsets, mPendingBackDropFrame, mPendingDisplayCutout, mPendingMergedConfiguration, mSurfaceControl, mTempInsets);
if (mSurfaceControl.isValid()) {
//复制 Surface:mNativeObject = nativeGetFromSurfaceControl(mNativeObject, other.mNativeObject)
mSurface.copyFrom(mSurfaceControl);
}
...
}
说明: mSurfaceControl 对象传递给 mWindowSession.relayout() 方法,最终在 WindowSurfaceController 的 getSurfaceControl() 方法中完成初始化。初始化后的 SurfaceControl 持有 native 层的 Surface 对象地址。mSurface.copyFrom() 方法从 SurfaceControl 中复制 native 层的 Surface 对象地址。
2.2 Session 到 WindowSurfaceController

(1)relayout
/frameworks/base/services/core/java/com/android/server/wm/Session.java
public int relayout(IWindow window, int seq, WindowManager.LayoutParams attrs, int requestedWidth, int requestedHeight,
int viewFlags, int flags, long frameNumber, Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,
Rect outVisibleInsets, Rect outStableInsets, Rect outsets, Rect outBackdropFrame, DisplayCutout.ParcelableWrapper cutout,
MergedConfiguration mergedConfiguration, SurfaceControl outSurfaceControl, InsetsState outInsetsState) {
...
int res = mService.relayoutWindow(this, window, seq, attrs, requestedWidth, requestedHeight, viewFlags,
flags, frameNumber, outFrame, outOverscanInsets, outContentInsets, outVisibleInsets, outStableInsets,
outsets, outBackdropFrame, cutout, mergedConfiguration, outSurfaceControl, outInsetsState);
...
}
(2)relayoutWindow
/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
public int relayoutWindow(Session session, IWindow client, int seq, LayoutParams attrs,
int requestedWidth, int requestedHeight, int viewVisibility, int flags,
long frameNumber, Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,
Rect outVisibleInsets, Rect outStableInsets, Rect outOutsets, Rect outBackdropFrame,
DisplayCutout.ParcelableWrapper outCutout, MergedConfiguration mergedConfiguration,
SurfaceControl outSurfaceControl, InsetsState outInsetsState) {
...
synchronized (mGlobalLock) {
//mWindowMap.get(client.asBinder())
final WindowState win = windowForClientLocked(session, client, false);
...
//mWinAnimator 在 WindowState 的构造方法中创建
WindowStateAnimator winAnimator = win.mWinAnimator;
if (viewVisibility != View.GONE) {
win.setRequestedSize(requestedWidth, requestedHeight);
}
win.setFrameNumber(frameNumber);
...
if (shouldRelayout) {
...
try {
//创建 SurfaceControl 对象,并拷贝给 outSurfaceControl
result = createSurfaceControl(outSurfaceControl, result, win, winAnimator);
}
...
}
...
}
...
}
说明:WindowStateAnimator 在 WindowState 的构造方法中创建,并将自身注入,即 WindowState 对象与 WindowStateAnimator 对象一一对应。
(3)createSurfaceControl
/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
private int createSurfaceControl(SurfaceControl outSurfaceControl, int result, WindowState win, WindowStateAnimator winAnimator) {
...
WindowSurfaceController surfaceController;
try {
...
//创建 WindowSurfaceController
surfaceController = winAnimator.createSurfaceLocked(win.mAttrs.type, win.mOwnerUid);
}
...
if (surfaceController != null) {
//获取 SurfaceController:outSurfaceControl.copyFrom(mSurfaceControl)
surfaceController.getSurfaceControl(outSurfaceControl);
...
}
...
}
(4)createSurfaceLocked
/frameworks/base/services/core/java/com/android/server/wm/WindowStateAnimator.java
WindowSurfaceController createSurfaceLocked(int windowType, int ownerUid) {
final WindowState w = mWin;
if (mSurfaceController != null) {
return mSurfaceController;
}
...
calculateSurfaceBounds(w, attrs, mTmpSize);
...
try {
...
mSurfaceController = new WindowSurfaceController(mSession.mSurfaceSession, attrs.getTitle().toString(),
width, height, format, flags, this, windowType, ownerUid);
...
}
...
return mSurfaceController;
}
说明:WindowSurfaceController 在 WindowStateAnimator 中单例存在,在创建 WindowSurfaceController 时,又将 WindowStateAnimator 注入,由此说明 WindowSurfaceController 和 WindowStateAnimator 一一对应,进一步说明 WindowState 与 WindowSurfaceController 、WindowStateAnimator 一一对应。
(5)WindowSurfaceController
/frameworks/base/services/core/java/com/android/server/wm/WindowSurfaceController.java
public WindowSurfaceController(SurfaceSession s, String name, int w, int h, int format,
int flags, WindowStateAnimator animator, int windowType, int ownerUid) {
mAnimator = animator;
mSurfaceW = w;
mSurfaceH = h;
title = name;
mService = animator.mService;
final WindowState win = animator.mWin;
mWindowType = windowType;
mWindowSession = win.mSession;
...
final SurfaceControl.Builder b = win.makeSurface().setParent(win.getSurfaceControl()).setName(name)
.setBufferSize(w, h).setFormat(format).setFlags(flags).setMetadata(METADATA_OWNER_UID, ownerUid);
//创建 SurfaceControl:new SurfaceControl()
mSurfaceControl = b.build();
}
说明: win.makeSurface() 调用的是 WindowState 的父类 WindowContainer 中的方法。
(6)getSurfaceControl
/frameworks/base/services/core/java/com/android/server/wm/WindowSurfaceController.java
void getSurfaceControl(SurfaceControl outSurfaceControl) {
outSurfaceControl.copyFrom(mSurfaceControl);
}
2.3 WindowContainer 到 SurfaceControl

(1)makeSurface
/frameworks/base/services/core/java/com/android/server/wm/WindowContainer.java
SurfaceControl.Builder makeSurface() {
final WindowContainer p = getParent();
return p.makeChildSurface(this);
}
说明:WindowSurfaceController 调用了 win.makeSurface(),而 WindowState 继承了 WindowContainer。
(2)makeChildSurface
/frameworks/base/services/core/java/com/android/server/wm/WindowContainer.java
//child 为 WindowState 对象
SurfaceControl.Builder makeChildSurface(WindowContainer child) {
final WindowContainer p = getParent();
return p.makeChildSurface(child).setParent(mSurfaceControl);
}
说明:这里顺着容器层次结构由下往上依次调用,直到某个容器重写了 makeChildSurface() 方法,先后经历的容器有 WindowState、WindowToken、Task、TaskStack、DisplayContent,这些容器中,只有 DisplayContent 重写 WindowContainer 的 makeChildSurface() 方法。
(3)makeChildSurface
/frameworks/base/services/core/java/com/android/server/wm/DisplayContent.java
SurfaceControl.Builder makeChildSurface(WindowContainer child) {
//child 为 WindowState 对象
SurfaceSession s = child != null ? child.getSession() : getSession();
final SurfaceControl.Builder b = mWmService.makeSurfaceBuilder(s).setContainerLayer();
if (child == null) {
return b;
}
//mWindowingLayer 属于 SurfaceControl 类,在 DisplayContent 的构造方法中创建
return b.setName(child.getName()).setParent(mWindowingLayer);
}
(4)getSession
/frameworks/base/services/core/java/com/android/server/wm/WindowState.java
SurfaceSession getSession() {
if (mSession.mSurfaceSession != null) {
return mSession.mSurfaceSession;
} else {
return getParent().getSession();
}
}
说明:mSession.mSurfaceSession 在 WindowState 初始化时创建,具体流程为:在 WindowState 中调用 attach() 方法中,再调用 Session 的 windowAddedLocked() 方法,详见→View添加过程。
(5)makeSurfaceBuilder
/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
//将 SurfaceBuilderFactory 的 make() 方法映射到 SurfaceControl.Builder 的有参构造方法
SurfaceBuilderFactory mSurfaceBuilderFactory = SurfaceControl.Builder::new;
SurfaceControl.Builder makeSurfaceBuilder(SurfaceSession s) {
return mSurfaceBuilderFactory.make(s);
}
(6)make
/frameworks/base/services/core/java/com/android/server/wm/SurfaceBuilderFactory.java
interface SurfaceBuilderFactory {
SurfaceControl.Builder make(SurfaceSession s);
};
说明:将 SurfaceBuilderFactory 的 make() 方法映射到 SurfaceControl.Builder 的有参构造方法,SurfaceSession 对象来自 Session。
(7)Build
/frameworks/base/core/java/android/view/SurfaceControl.Build.java
public Builder(SurfaceSession session) {
mSession = session;
}
(8)SurfaceControl
/frameworks/base/core/java/android/view/SurfaceControl.Build.java
public SurfaceControl build() {
...
return new SurfaceControl(mSession, mName, mWidth, mHeight, mFormat, mFlags, mParent, mMetadata);
}
声明:本文转自【framework】Surface创建流程
【framework】Surface创建流程的更多相关文章
- android6.0 Activity(四) Surface创建
原文:http://blog.csdn.net/luoshengyang/article/details/8303098.原文代码比較老了,可是核心不变.在原文基础上改动了一些代码,以及增加自己 ...
- Magento代码之订单创建流程
Magento代码之订单创建流程 直接看代码吧.下面的代码是如何通过程序创建一个完美订单. <?php require_once 'app/Mage. ...
- ADF 项目创建流程
ADF 项目创建流程: 1.首先建好应用 2.创建model,UI 3.创建EO,VO,AO, VL 4.设置EO的属性 5.新建lov 6.设置VO的View Accessors,并设置Attrib ...
- MFC中SDI程序创建流程的回顾
SDI程序创建流程的回顾 从CWinApp.InitialInstance()开始, 1.首先应用程序对象创建文档模板; CSingleDocTemplate* pDocTemplate; pDocT ...
- 【Java基础】Java类的加载和对象创建流程的详细分析
相信我们在面试Java的时候总会有一些公司要做笔试题目的,而Java类的加载和对象创建流程的知识点也是常见的题目之一.接下来通过实例详细的分析一下. 实例问题 实例代码 Parent类 package ...
- Java类的加载和对象创建流程的详细分析
相信我们在面试Java的时候总会有一些公司要做笔试题目的,而Java类的加载和对象创建流程的知识点也是常见的题目之一.接下来通过实例详细的分析一下: package com.test; public ...
- OpenStack Nova虚拟机创建流程解析
https://yikun.github.io/2017/09/27/OpenStack-Nova%E8%99%9A%E6%8B%9F%E6%9C%BA%E5%88%9B%E5%BB%BA%E6%B5 ...
- 8 云计算系列之Horizon的安装与虚拟机创建流程
preface 在上一章节中,我们可以在无web管理界面上创建并启动虚拟机,虽然可以这么做,但是敲命令太繁琐,所以此时我们可以安装openstack web管理界面,通过web界面的图形化操作open ...
- iOS开发:Framework的创建
转载自:http://jonzzs.cn/2017/06/01/iOS%20开发笔记/[iOS%20开发]将自己的框架打包成%20Framework%20的方法/ 环境:Xcode 8 创建 Fram ...
- k8s 基础 pod创建流程
Pod是Kubernetes中最基本的部署调度单元,可以包含container,逻辑上表示某种应用的一个实例.例如一个web站点应用由前端.后端及数据库构建而成,这三个组件将运行在各自的容器中,那么我 ...
随机推荐
- OpenKruise :Kubernetes背后的托底
本文分享自华为云社区<OpenKruise核心能力和工作原理>,作者:可以交个朋友. 一. 诞生背景 Kubernetes 自身提供的应用部署管理功能,无法满足大规模应用场景的需求,例如应 ...
- 京东哥伦布即时设计平台ChatGPT落地实践
一.平台介绍 即时设计平台是一个即时搭建c端楼层的开发平台,支持通过导入relay设计稿url完成Ui2Code,在此基础上完成前端可视化搭建,同时支持通过ChatGPT完成一句话需求,搭建后的楼层自 ...
- 京东云开发者|提高IT运维效率,深度解读京东云AIOps落地实践
基于深度学习对运维时序指标进行异常检测,快速发现线上业务问题 时间序列的异常检测是实际应用中的一个关键问题,尤其是在 IT 行业.我们没有采用传统的基于阈值的方法来实现异常检测,而是通过深度学习提出了 ...
- 开源项目01--WTM
一.项目名称:WTM 项目所用技术栈: wtm mvvm mvc aspnetcore dotnetcore react vue layui layui-admin element-ui ncc等 项 ...
- Golang并发控制方式有几种?
Go语言中的goroutine是一种轻量级的线程,其优点在于占用资源少.切换成本低,能够高效地实现并发操作.但如何对这些并发的goroutine进行控制呢? 一提到并发控制,大家最先想到到的是锁.Go ...
- Rocketmq学习4——Broker消息持久化原理源码浅析
一丶前言 在<Rocketmq学习3--消息发送原理源码浅析>中,我们学习了消息发送的要点: 本地缓存+rpc 请求namesever + 定时刷新,topic路由信息 负载均衡的选择一个 ...
- github clone或访问慢
做技术的我们经常会访问github.com,有时出现github访问非常慢或者git clone速度很慢,git push也很慢 原因很简单:github被高高的墙屏蔽了. 所以解决方案就是手动把 c ...
- 《字节码编程》PDF107页,11万字。既然市面缺少ASM、Javassist、Byte-buddy成体系的学习资料,那我来!
作者:小傅哥 博客:https://bugstack.cn - 汇总系列原创专题文章 沉淀.分享.成长,让自己和他人都能有所收获! 让人怪不好意思的,说是出书有点膨胀,毕竟这不是走出版社的流程,选题. ...
- vue-router.esm.js:2065 Uncaught (in promise) Error: Redirected when going from "/login?redirect=%2Fhome" to "/home" via a navigation guard.
原因: vue-router路由版本更新产生的问题,导致路由跳转失败抛出该错误; 真正的原因是由于返回了一个Promise对象, 正常的跳转由then方法执行 当正常的路由跳转, 被"路 ...
- Windows安装MySQL到最后卡主无响应处理办法
安装mysql-5.5.62-winx64到最后Ready to execute ... 生效配置时卡主无响应 最有效,最快的解决办法 就是:重启电脑 或者 关闭电脑,在开机,找到MySQL安装目录, ...