Android的Surface的创建
ViewRootImpl
管理着整个view tree。 对于ViewRootImpl.setView()
,我们可以简单的把它当做一个UI渲染操作
的入口。
http://androidxref.com/6.0.1_r10/xref/frameworks/base/core/java/android/view/WindowManagerImpl.java
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
...
//mWindowSession是一个aidl,ViewRootImpl利用它来和WindowManagerService交互
//mWindow是一个aidl,WindowManagerService可以利用这个对象与服务端交互
//mAttachInfo可以理解为是一个data bean,可以跨进程传递
res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(), mWinFrame,
mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
mAttachInfo.mOutsets, mAttachInfo.mDisplayCutout, mInputChannel);
...
}
ViewRootImpl.setView()
方法会向WindowManagerService
请求添加一个Window
,mWindowSession.addToDisplay()
跨进程最终调用到了WindowManagerService.addWindow()
:public int addWindow(Session session, IWindow client...) {
...
//WindowState用来描述一个Window
final WindowState win = new WindowState(this, session, client, token, parentWindow,
appOp[0], seq, attrs, viewVisibility, session.mUid,
session.mCanAddInternalSystemWindow);
...
win.attach(); //会创建一个SurfaceSession mWindowMap.put(client.asBinder(), win); //mWindowMap是WindowManagerService用来保存当前所有Window新的的集合
...
win.mToken.addWindow(win); //一个token下会有多个win state。 其实token与PhoneWindow是一一对应的。
...
}
void attach() {
if (WindowManagerService.localLOGV) Slog.v(
TAG, "Attaching " + this + " token=" + mToken
+ ", list=" + mToken.windows);
mSession.windowAddedLocked();
}
WindowState
是WindowManagerService
用来描述应用程序的一个Window
的对象。上面注释我标注了win.attach()
,这个方法可以说是Window
与SurfaceFlinger
链接的起点,它最终会调用到Session.windowAddedLocked()
:void windowAddedLocked(String packageName) {
...
if (mSurfaceSession == null) {
...
mSurfaceSession = new SurfaceSession();
...
}
}
http://androidxref.com/6.0.1_r10/xref/frameworks/base/core/java/android/view/SurfaceSession.java
//SurfaceSession类的构造方法
public final class SurfaceSession {
private long mNativeClient; // SurfaceComposerClient* public SurfaceSession() {
mNativeClient = nativeCreate();
}
这里调用了native方法nativeCreate()
,这个方法其实是返回了一个SurfaceComposerClient指针
。那这个对象是怎么创建的呢?
SurfaceComposerClient的创建
http://androidxref.com/6.0.1_r10/xref/frameworks/base/core/jni/android_view_SurfaceSession.cpp
static jlong nativeCreate(JNIEnv* env, jclass clazz) {
SurfaceComposerClient* client = new SurfaceComposerClient(); //构造函数其实并没有做什么
client->incStrong((void*)nativeCreate);
return reinterpret_cast<jlong>(client);
}
SurfaceComposerClient
对象。并返回它的指针。这个对象一个应用程序就有一个,它是应用程序与SurfaceFlinger
沟通的桥梁,为什么这么说呢?在SurfaceComposerClient指针
第一次使用时会调用下面这个方法://这个方法在第一次使用SurfaceComposerClient的指针的时候会调用
void SurfaceComposerClient::onFirstRef() {
....
sp<ISurfaceComposerClient> conn;
//sf 就是SurfaceFlinger
conn = (rootProducer != nullptr) ? sf->createScopedConnection(rootProducer) :
sf->createConnection();
...
}
即通过SurfaceFlinger(它本身具有跨进程通信的能力)
创建了一个ISurfaceComposerClient
对象:
http://androidxref.com/6.0.1_r10/xref/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
sp<ISurfaceComposerClient> SurfaceFlinger::createConnection() {
return initClient(new Client(this)); //initClient这个方法其实并没有做什么,
}
Client
对象,Client
实现了ISurfaceComposerClient
接口。是一个可以跨进程通信的aidl对象。即SurfaceComposerClient
可以通过它来和SurfaceFlinger
通信。除此之外它还可以创建Surface
,并且维护一个应用程序的所有Layer(下文会分析到它是什么)
。它是一个十分重要的对象,我们先来看一下它的组成,它所涉及的其他东西在下文分析中都会讲到:http://androidxref.com/6.0.1_r10/xref/frameworks/native/services/surfaceflinger/Client.h
class Client : public BnSurfaceComposerClient
{
public:
...
void attachLayer(const sp<IBinder>& handle, const sp<Layer>& layer);
void detachLayer(const Layer* layer);
...
private:
// ISurfaceComposerClient interface。 gbp很重要,它维护这一个应用程序的渲染 Buffer队列
virtual status_t createSurface(...sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp); virtual status_t destroySurface(const sp<IBinder>& handle); //跨进程通信方法
virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
... // constant
sp<SurfaceFlinger> mFlinger; // protected by mLock
DefaultKeyedVector< wp<IBinder>, wp<Layer> > mLayers; // 一个应用程序的所有Layer
...
};
经过上面这一顿源码分析,我们大概知道了ViewRootImpl.setView()
所引发的主要操作:
WindowManagerService
创建了一个WindowState
。用来表示客户端的一个Window
WindowManagerService
创建了一个SurfaceSession
,SurfaceSession
会与SurfaceFlinger
构建链接,创建了一个SurfaceComposerClient
对象,一个应用程序只具有一个这个对象。SurfaceComposerClient
创建了一个Client
, 这个对象十分重要,它维护这应用程序的渲染核心数据,并负责与SurfaceFlinger
通信。
经过上面的步骤,应用程序的ViewRootImpl
已经被WindowManagerService
识别,并且应用程序已经与SurfaceFlinger
建立连接。即创建了SurfaceComposerClient
和Client
对象
文章开始就已经说了Surface
是Window(ViewRootImpl)
的UI载体,那Surface
是在哪里创建的呢?
Surface的创建
其实一个ViewRootImpl
就对应一个Surface
。
http://androidxref.com/6.0.1_r10/xref/frameworks/base/core/java/android/view/Surface.java
这点可以通过ViewRootImpl
的源码看出:
即ViewRootImpl
在构造的时候就new 了一个 Surface
。但其实这个新new的Surface
并没有什么逻辑,它的构造函数是空的。
http://androidxref.com/6.0.1_r10/xref/frameworks/base/core/java/android/view/ViewRootImpl.java
public final class ViewRootImpl implements ViewParent,
View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks {
//...
public final Surface mSurface = new Surface();
//...
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
...
requestLayout(); //susion 请求layout。先添加到待渲染队列中
...
res = mWindowSession.addToDisplay(mWindow, ...); //WindowManagerService会创建mWindow对应的WindowState
...
}
@Override
public void requestLayout() {
if (!mHandlingLayoutInLayoutRequest) {
checkThread();
mLayoutRequested = true;
scheduleTraversals();
}
} }
即在向WindowManagerService
请求创建WindowState
之前,调用了requestLayout()
,这个方法会引起ViewRootImpl
所管理的整个view tree的重新渲染。它最终会调用到scheduleTraversals()
:
http://androidxref.com/6.0.1_r10/xref/frameworks/base/core/java/android/view/ViewRootImpl.java
void scheduleTraversals() {
...
mChoreographer.postCallback(Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
...
}
scheduleTraversals()
会通过Choreographer
来post一个mTraversalRunnable
,Choreographer
接收显示系统的时间脉冲(垂直同步信号-VSync信号,16ms发出一次),在下一个frame渲染时控制执行这个mTraversalRunnable
。
但是mTraversalRunnable
的执行至少要在应用程序与SurfaceFlinger
建立连接之后。这是因为渲染操作是由SurfaceFlinger
负责调度了,如果应用程序还没有与SurfaceFlinger
创建连接,那SurfaceFlinger
当然不会渲染这个应用程序。所以在执行完mWindowSession.addToDisplay(mWindow, ...)
之后,才会执行mTraversalRunnable
:
final class TraversalRunnable implements Runnable {
@Override
public void run() {
doTraversal();
}
}
doTraversal()
会调用到ViewRootImpl.performTraversals()
,大部分同学可能知道这个方法是一个view tree
的measure/layout/draw
的控制方法:
private void performTraversals() {
finalView host = mView; //mView是一个Window的根View,对于Activity来说就是DecorView
...
relayoutWindow(params, viewVisibility, insetsPending);
...
performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
...
performLayout(lp, mWidth, mHeight);
...
performDraw();
...
}
Surface
的具体创建就由relayoutWindow(params, viewVisibility, insetsPending)
这个方法来完成的。这个方法会通过IPC
调用到WindowManagerService.relayoutWindow()
:
http://androidxref.com/6.0.1_r10/xref/frameworks/base/core/java/android/view/ViewRootImpl.java
private int relayoutWindow(WindowManager.LayoutParams params, ...) throws RemoteException {
...
int relayoutResult = mWindowSession.relayout(mWindow,..., mSurface);
...
}
mWindowSession.relayout()
方法的很多参数,不过有一个十分重要的参数我没有省略,就是mSurface
。前面已经分析了它就是一个空的Surface
对象。其实:
真正的Surface创建是由SurfaceControl
完成的,应用程序ViewRootImpl
的Surface
只是一个指针,指向这个Surface
下面就来看一下SurfaceControl
是如何创建Surface
的:
mWindowSession.relayout()
会调用到WindowManagerService.relayoutWindow()
:
//这里的outSurface其实就是ViewRootImpl中的那个Surface
public int relayoutWindow(Session session, IWindow client....Surface outSurface){
...
result = createSurfaceControl(outSurface, result, win, winAnimator);
...
} private int createSurfaceControl(Surface outSurface, int result, WindowState win,WindowStateAnimator winAnimator) {
...
surfaceController = winAnimator.createSurfaceLocked(win.mAttrs.type, win.mOwnerUid);
...
surfaceController.getSurface(outSurface);
}
winAnimator.createSurfaceLocked
实际上是创建了一个SurfaceControl
。即上面是先构造SurfaceControl
,然后在构造Surface
。
SurfaceControl createSurfaceLocked() {
final WindowState w = mWin;
if (mSurfaceControl == null) {
//...
mSurfaceFormat = format;
if (DEBUG_SURFACE_TRACE) {
mSurfaceControl = new SurfaceTrace(
mSession.mSurfaceSession,
attrs.getTitle().toString(),
width, height, format, flags);
} else {
mSurfaceControl = new SurfaceControl(
mSession.mSurfaceSession,
attrs.getTitle().toString(),
width, height, format, flags);
}
//...
}
return mSurfaceControl;
}
SurfaceControl的创建
winAnimator.createSurfaceLocked
其实是通过SurfaceControl
的构造函数创建了一个SurfaceControl
对象,这个对象的作用其实就是负责维护Surface
,Surface
其实也是由这个对象负责创建的,我们看一下这个对象的构造方法:
http://androidxref.com/6.0.1_r10/xref/frameworks/base/core/java/android/view/SurfaceControl.java
long mNativeObject; //成员指针变量,指向native创建的SurfaceControl private SurfaceControl(SurfaceSession session, String name, int w, int h, int format, int flags,
SurfaceControl parent, int windowType, int ownerUid){
...
mNativeObject = nativeCreate(session, name, w, h, format, flags,
parent != null ? parent.mNativeObject : 0, windowType, ownerUid);
...
}
即调用了nativeCreate()
并返回一个SurfaceControl
指针:
http://androidxref.com/6.0.1_r10/xref/frameworks/native/libs/gui/SurfaceControl.cpp
static jlong nativeCreate(JNIEnv* env, ...) {
//这个client其实就是前面创建的SurfaceComposerClinent
sp<SurfaceComposerClient> client(android_view_SurfaceSession_getClient(env, sessionObj));
sp<SurfaceControl> surface; //创建成功之后,这个指针会指向新创建的SurfaceControl
status_t err = client->createSurfaceChecked(String8(name.c_str()), w, h, format, &surface, flags, parent, windowType, ownerUid);
...
return reinterpret_cast<jlong>(surface.get()); //返回这个SurfaceControl的地址
}
即调用到SurfaceComposerClient.createSurfaceChecked()
:
http://androidxref.com/6.0.1_r10/xref/frameworks/native/libs/gui/SurfaceComposerClient.cpp
//outSurface会指向新创建的SurfaceControl
status_t SurfaceComposerClient::createSurfaceChecked(...sp<SurfaceControl>* outSurface..)
{
sp<IGraphicBufferProducer> gbp; //这个对象很重要
...
err = mClient->createSurface(name, w, h, format, flags, parentHandle, windowType, ownerUid, &handle, &gbp);
if (err == NO_ERROR) {
//SurfaceControl创建成功, 指针赋值
*outSurface = new SurfaceControl(this, handle, gbp, true);
}
return err;
}
Client.createSurface()
来创建一个Surface
。在创建时有一个很重要的参数sp<IGraphicBufferProducer> gbp
,在下面源码分析中我们也要重点注意它。这是因为应用所渲染的每一帧,实际上都会添加到IGraphicBufferProducer
中,来等待SurfaceFlinger
的渲染。http://androidxref.com/6.0.1_r10/xref/frameworks/native/services/surfaceflinger/Client.cpp
status_t Client::createSurface(...)
{
...
//gbp 直接透传到了SurfaceFlinger
return mFlinger->createLayer(name, this, w, h, format, flags, windowType, ownerUid, handle, gbp, &parent);
}
Surface
在SurfaceFlinger
中对应的实体其实是Layer
我们继续看一下mFlinger->createLayer()
http://androidxref.com/6.0.1_r10/xref/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
status_t SurfaceFlinger::createLayer(const String8& name,const sp<Client>& client...)
{
status_t result = NO_ERROR;
sp<Layer> layer; //将要创建的layer
switch (flags & ISurfaceComposerClient::eFXSurfaceMask) {
case ISurfaceComposerClient::eFXSurfaceNormal:
result = createBufferLayer(client,
uniqueName, w, h, flags, format,
handle, gbp, &layer); // 注意gbp,这时候还没有构造呢!
break;
... //Layer 分为好几种,这里不全部列出
}
...
result = addClientLayer(client, *handle, *gbp, layer, *parent); //这个layer和client相关联, 添加到Client的mLayers集合中。
...
return result;
}
从SurfaceFlinger.createLayer()
方法可以看出Layer
分为好几种。我们这里只对普通的BufferLayer
的创建做一下分析,看createBufferLayer()
:
http://androidxref.com/6.0.1_r10/xref/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
status_t SurfaceFlinger::createBufferLayer(const sp<Client>& client... sp<Layer>* outLayer)
{
...
sp<BufferLayer> layer = new BufferLayer(this, client, name, w, h, flags);
status_t err = layer->setBuffers(w, h, format, flags); //设置layer的宽高
if (err == NO_ERROR) {
*handle = layer->getHandle(); //创建handle
*gbp = layer->getProducer(); //创建 gbp IGraphicBufferProducer
*outLayer = layer; //把新建的layer的指针拷贝给outLayer,这样outLayer就指向了新建的BufferLayer
}
return err;
}
前面我说过IGraphicBufferProducer(gbp)
是一个很重要的对象,它涉及到SurfaceFlinger
的渲染逻辑,下面我们就看一下这个对象的创建逻辑:
IGraphicBufferProducer(gbp)的创建
sp<IGraphicBufferProducer> BufferLayer::getProducer() const {
return mProducer;
}
即mProducer
其实是Layer
的成员变量,它的创建时机是Layer
第一次被使用时:
void BufferLayer::onFirstRef() {
...
BufferQueue::createBufferQueue(&producer, &consumer, true);
mProducer = new MonitoredProducer(producer, mFlinger, this);
...
}
所以mProducer
的实例是MonitoredProducer
,但其实它只是一个装饰类,它实际功能都委托给构造它的参数producer
:
BufferQueue.cpp
void BufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
...
sp<IGraphicBufferProducer> producer(new BufferQueueProducer(core, consumerIsSurfaceFlinger));
sp<IGraphicBufferConsumer> consumer(new BufferQueueConsumer(core)); //注意这个consumer
...
*outProducer = producer;
*outConsumer = consumer;
}
所以实际实现mProducer
的工作的queueProducer
是BufferQueueProducer
。
所以构造一个SurfaceControl
所做的工作就是创建了一个SurfaceControl
,并让SurfaceFlinger
创建了一个对应的Layer
,Layer
中有一个IGraphicBufferProducer
,它的实例是BufferQueueProducer
。
可以用下面这个图来描述SurfaceControl
的创建过程:
从SurfaceControl中获取Surface
我们回看WindowManagerService.createSurfaceControl()
, 来看一下java层的Surface
对象到底是个什么:
http://androidxref.com/6.0.1_r10/xref/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
private int createSurfaceControl(Surface outSurface, int result, WindowState win,WindowStateAnimator winAnimator) {
...
surfaceController = winAnimator.createSurfaceLocked(win.mAttrs.type, win.mOwnerUid);
...
surfaceController.getSurface(outSurface);
}
winAnimator.createSurfaceLocked
的整个过程,我们看一下surfaceController.getSurface(outSurface)
, surfaceController
是WindowSurfaceController
的实例://WindowSurfaceController.java
void getSurface(Surface outSurface) {
outSurface.copyFrom(mSurfaceControl);
} //Surface.java
public void copyFrom(SurfaceControl other) {
...
long surfaceControlPtr = other.mNativeObject;
...
long newNativeObject = nativeGetFromSurfaceControl(surfaceControlPtr);
...
mNativeObject = ptr; // mNativeObject指向native创建的Surface
}
即Surface.copyFrom()
方法调用nativeGetFromSurfaceControl()
来获取一个指针,这个指针是根据前面创建的SurfaceControl
的指针来寻找的,即传入的参数surfaceControlPtr
:
android_view_Surface.cpp
static jlong nativeGetFromSurfaceControl(JNIEnv* env, jclass clazz, jlong surfaceControlNativeObj) {
sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(surfaceControlNativeObj)); //把java指针转化内native指针
sp<Surface> surface(ctrl->getSurface()); //直接构造一个Surface,指向 ctrl->getSurface()
if (surface != NULL) {
surface->incStrong(&sRefBaseOwner); //强引用
}
return reinterpret_cast<jlong>(surface.get());
}
这里的ctrl
指向前面创建的SurfaceControl
,继续追溯ctrl->getSurface()
:
sp<Surface> SurfaceControl::getSurface() const
{
Mutex::Autolock _l(mLock);
if (mSurfaceData == 0) {
return generateSurfaceLocked();
}
return mSurfaceData;
} sp<Surface> SurfaceControl::generateSurfaceLocked() const
{
//这个mGraphicBufferProducer其实就是上面分析的BufferQueueProducer
mSurfaceData = new Surface(mGraphicBufferProducer, false);
return mSurfaceData;
}
即直接new了一个nativie的Surface
返回给java层,java层的Surface
指向的就是native层的Surface
。
所以Surface
的实际创建可以用下图表示:
经过上面这个图,也可以理解SurfaceControl
为什么叫SurfaceControl
了。
Android的Surface的创建的更多相关文章
- [转]Android系统Surface机制的SurfaceFlinger服务简要介绍和学习计划
转自:Android系统Surface机制的SurfaceFlinger服务简要介绍和学习计划 前面我们从Android应用程序与SurfaceFlinger服务的关系出发,从侧面简单学习了Surfa ...
- Android系统Surface机制的SurfaceFlinger服务的线程模型分析
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/8062945 在前面两篇文章中,我们分析了Sur ...
- Android系统Surface机制的SurfaceFlinger服务对帧缓冲区(Frame Buffer)的管理分析
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/8046659 在前文中,我们分析了Surface ...
- Android系统Surface机制的SurfaceFlinger服务的启动过程分析
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/8022957 在前面一篇文章中,我们简要介绍了A ...
- Android使用surface直接显示yuv数据(三)
在本文中,Java创建UI和关节JNI经营层surface直接显示yuv数据(yv12).发展环境Android 4.4,驰A23平台. package com.example.myyuvviewer ...
- 「Android」 Surface分析
本篇针对Surface模块进行分析,从Java层的Activity创建开始,到ViewRoot.WindowsManagerService,再到JNI层和Native层. 首先推荐一个Android源 ...
- Android用surface直接显示yuv数据(三)
本文用Java创建UI并联合JNI层操作surface来直接显示yuv数据(yv12),开发环境为Android 4.4,全志A23平台. package com.example.myyuvviewe ...
- Android系统Surface机制的SurfaceFlinger服务渲染应用程序UI的过程分析
参考:Android系统Surface机制的SurfaceFlinger服务渲染应用程序UI的过程分析 一句话概括一下Android应用程序显示的过程:Android应用程序调用SurfaceFlin ...
- [Android Pro] Android 官方推荐 : DialogFragment 创建对话框
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/37815413 1. 概述 DialogFragment在android 3.0时 ...
随机推荐
- 表格变色示例中发现的问题——attr()与prop()
在练习jQuery表格变色例子过程中,发现了一下几个问题: 在IEEdge浏览器中切换选中行会出现上一个表格行背景色被吃掉的情况: 在chrome中从上向下单击行中任意单元可以选中该行,而从下往上单击 ...
- Python爬虫之selenium高级功能
Python爬虫之selenium高级功能 原文地址 表单操作 元素拖拽 页面切换 弹窗处理 表单操作 表单里面会有文本框.密码框.下拉框.登陆框等. 这些涉及与页面的交互,比如输入.删除.点击等. ...
- modinfo - 显示当前内核模块信息
总览 modinfo [ options ] <module_file> 描述 modinfo 工具软件用来对内核模块的目标文件 module_file 进行测试并打印输出相关信息. 选项 ...
- mingetty - 控制台最小的 getty
总览 SYNOPSIS mingetty [--noclear] [--nonewline] [--noissue] [--nohangup] [--nohostname] [--long-hostn ...
- 对 django rest framework框架的认识
- 路由 - 可以通过as_view传参数,根据请求方式不同执行相应的方法 - 可以在url中设置一个结尾,类似于: .json - 视图 - 帮助开发者提供了一些类,并在类中提供了多个方法以供我们使 ...
- CSS初识
CSS:层叠样式表,控制网页数据样式显示,使得数据的表现和内容分离 CSS的引入方式 使用元素内嵌样式表:例<a style=”font-size:40px”></a>表示在a ...
- PAT Basic 1026 程序运行时间 (15 分)
要获得一个 C 语言程序的运行时间,常用的方法是调用头文件 time.h,其中提供了 clock() 函数,可以捕捉从程序开始运行到 clock() 被调用时所耗费的时间.这个时间单位是 clock ...
- Laplace's equation
链接:https://en.wikipedia.org/wiki/Laplace%27s_equation
- Qt 打包release发布问题
除了使用depens查看exe依赖的dll,本文使用qt5.13自带的打包工具windeployqt.exe tips: demo.exe(x86) :C:\Qt\Qt5.12.3\5.12.3\ms ...
- 进度对话框QProgressDialog
继承于 QDialog import sys,time from PyQt5.QtWidgets import QApplication, QWidget,QPushButton,QProgress ...