写在前面
Surface 是整个 Android 显示框架中最重要也是最基础的一个概念,它承担着 App UI 的显示需求,App 需要展示的 UI 都必须要画到这个 Surface 上才能被显示出来。通过学习本章内容,你会了解:
- 什么是
Surface - App 是如何获取
Surface Surface/SurfaceControl/Layer这些基本概念的区别与联系
什么是 Surface
我们知道 App 的 UI 最终都是通过 SurfaceFlinger 合成之后,然后提交给 Display 进行显示。而 Surface 就是 App 和 SurfaceFlinger 之间的桥梁。 我们从源码的角度来分析 Surface
arduino
// frameworks/native/libs/gui/include/gui/Surface.h
class Surface
: public ANativeObjectBase<ANativeWindow, Surface, RefBase>
{
sp<IGraphicBufferProducer> getIGraphicBufferProducer() const;
...
virtual int dequeueBuffer(ANativeWindowBuffer** buffer, int* fenceFd);
virtual int queueBuffer(ANativeWindowBuffer* buffer, int fenceFd);
...
}
getIGraphicBufferProducer :从名字可以看出,这个变量是 GraphicBuffer 的生产者 。GraphicBuffer 是什么呢? GraphicBuffer 代表着一块可以被 CPU/GPU 访问的图像缓冲区。App 可以通过第三方渲染引擎,如 OpenGL/SKia 等, 把 UI 渲染到这个一块缓冲区。GraphicBuffer 后面会单独拿一下小节讲解。
dequeueBuffer : 通过 dequeueBuffer 可以从 Buffer Queue 中获取一块 GraphicBuffer,用于 App 进行渲染。
queueBuffer :通过 queueBuffer 可以把渲染好的 GraphicBuffer 提交到 Buffer Queue 中,然后再提交给 SurfaceFlinger 进行合成,最终提交到 Display 进行显示。
那么 Buffer Queue 是由谁管理的呢? 为什么 Surface 的 dequeueBuffer/queueBuffer 就能从 Buffer Queue 中获取 Buffer 呢?实际上 Buffer Queue 管理以及 dequeueBuffer/queueBuffer 的实现都是由 BLASTBufferQueue 实现的,这个后面会单独拿一个小节来说。
那么 Surface 是什么时候被创建的呢?Surface 是运行在哪个进程?
Surface/SurfaceControl/Layer 创建
Surface 的创建是在 Activity 的 ViewRootImpl 进行 performTraversal (至于什么时候进行 performTraversal,后面会具体分析,先说结论:当 Vsync 来的时候,Activity 的 ViewRootImpl 会进行 performTraversal) 时候。
csharp
// frameworks/base/core/java/android/view/ViewRootImpl.java
private void performTraversals() {
...
relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
...
}
csharp
private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,boolean insetsPending){
...
relayoutResult = mWindowSession.relayout(mWindow, params,
requestedWidth, requestedHeight, viewVisibility,
insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0,
mRelayoutSeq, mLastSyncSeqId, mRelayoutResult);
...
}
其中 mRelayoutResult 包含了一个重要的参数 mSurfaceControl,这里留意一下,后面会具体说到这个 mSurfaceControl。
mWindowSession 是一个 AIDL 接口, 所以 mWindowSession.relayout 是一个跨进程的方法,它的实现在另外一个进程中(WMS 所在的进程)
java
// frameworks/base/services/core/java/com/android/server/wm/Session.java
public int relayout(IWindow window, WindowManager.LayoutParams attrs,
int requestedWidth, int requestedHeight, int viewFlags, int flags, int seq,
int lastSyncSeqId, WindowRelayoutResult outRelayoutResult) {
int res = mService.relayoutWindow(this, window, attrs, requestedWidth,
requestedHeight, viewFlags, flags, seq, lastSyncSeqId, outRelayoutResult);
return res;
}
这里的 mService 指的就是 WindowServiceManager, 所以 App 进程中通过 mWindowSession.relayout 最终通过跨进程调用到了 WindowManagerService 的 relayoutWindow
java
// frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
public int relayoutWindow(Session session, IWindow client, LayoutParams attrs,
int requestedWidth, int requestedHeight, int viewVisibility, int flags, int seq,
int lastSyncSeqId, WindowRelayoutResult outRelayoutResult) {
final ClientWindowFrames outFrames;
final MergedConfiguration outMergedConfiguration;
final SurfaceControl outSurfaceControl;
final InsetsState outInsetsState;
final InsetsSourceControl.Array outActiveControls;
if (outRelayoutResult != null) {
...
把 SurfaceControl 从 WindowRelayoutResult 拿出来
outSurfaceControl = outRelayoutResult.surfaceControl;
...
}
// 创建一个 SurfaceControl
result = createSurfaceControl(outSurfaceControl, result, win, winAnimator);
...
}
SurfaceControl 创建
csharp
// frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
private int createSurfaceControl(SurfaceControl outSurfaceControl, int result,
WindowState win, WindowStateAnimator winAnimator) {
SurfaceControl surfaceControl;
try {
surfaceControl = winAnimator.createSurfaceLocked();
} finally {
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
if (surfaceControl != null) {
winAnimator.getSurfaceControl(outSurfaceControl);
ProtoLog.i(WM_SHOW_TRANSACTIONS, "OUT SURFACE %s: copied", outSurfaceControl);
}
...
}
在 createSurfaceControl 中
WindowStateAnimator.createSurfaceLocked创建一个surfaceControl(这里其实可以猜到Surface和SurfaceControl的关系很暧昧了,明明是创建一个SurfaceControl, 但是方法名却是createSurfaceLocked)- 把创建的
SurfaceControl通过getSurfaceControlcopy 给outSurfaceControl, 这个outSurfaceControl也就是在RootViewImpl创建并作为参数传过来的 WMS的SurfaceControl。所以把创建好的 SurfaceControl copy 给 outSurfaceControl, 也就是把这个的SurfaceControl返回给了RootViewImpl所持有
接下来继续分析 WindowStateAnimator.createSurfaceLocked
scss
// frameworks/base/services/core/java/com/android/server/wm/WindowStateAnimator.java
SurfaceControl createSurfaceLocked() {
...
mSurfaceControl = mWin.makeSurface()
.setParent(mWin.mSurfaceControl)
.setName(mTitle)
.setFormat(format)
.setFlags(flags)
.setMetadata(METADATA_WINDOW_TYPE, attrs.type)
.setMetadata(METADATA_OWNER_UID, mSession.mUid)
.setMetadata(METADATA_OWNER_PID, mSession.mPid)
.setCallsite("WindowSurfaceController")
.setBLASTLayer().build();
...
}
这里会对 SurfaceControl 做一些参数设置, 然后会调用 SurfaceControl.Builder 的 build 来构建 SurfaceControl
csharp
// frameworks/base/core/java/android/view/SurfaceControl.java
public SurfaceControl build() {
...
return new SurfaceControl(
mSession, mName, mWidth, mHeight, mFormat, mFlags, mParent, mMetadata, mLocalOwnerView, mCallsite);
}
这里会调用 SurfaceControl 的带参构造函数
csharp
// frameworks/base/core/java/android/view/SurfaceControl.java
private SurfaceControl(SurfaceSession session, String name, int w, int h, int format, int flags,
...
nativeObject = nativeCreate(session, name, w, h, format, flags,
parent != null ? parent.mNativeObject : 0, metaParcel);
...
}
nativeCreate 是一个 JNI 方法,继续来看在 native 的实现
kotlin
// frameworks/base/core/jni/android_view_SurfaceControl.cpp
static jlong nativeCreate(JNIEnv* env, jclass clazz, jobject sessionObj,
jstring nameStr, jint w, jint h, jint format, jint flags, jlong parentObject,
jobject metadataParcel) {
ScopedUtfChars name(env, nameStr);
sp<SurfaceComposerClient> client;
sp<SurfaceControl> surface;
...
status_t err = client->createSurfaceChecked(String8(name.c_str()), w, h, format, &surface,
flags, parentHandle, std::move(metadata));
surface->incStrong((void *)nativeCreate);
return reinterpret_cast<jlong>(surface.get());
}
SurfaceComposerClient->createSurfaceChecked
c
status_t SurfaceComposerClient::createSurfaceChecked(const String8& name, uint32_t w, uint32_t h,
PixelFormat format,
sp<SurfaceControl>* outSurface, int32_t flags,
const sp<IBinder>& parentHandle,
LayerMetadata metadata,
uint32_t* outTransformHint) {
...
gui::CreateSurfaceResult result;
// 跨进程调用 createSurface
binder::Status status = mClient->createSurface(std::string(name.c_str()), flags,
parentHandle, std::move(metadata), &result);
...
// 最终创建了 C++ 层的 SurfaceControl
*outSurface = sp<SurfaceControl>::make(this, result.handle, result.layerId,
toString(result.layerName), w, h, format,
result.transformHint, flags);
}
return err;
}
mClient是ISurfaceComposerClient接口的 Binder 客户端代理对象,所以mClient->createSurface是一个 Binder call,它的服务端实现在 SurfaceFlinger 所运行的进程。 所以Create Surface由WMS所在进程跑到了SurfaceFlinger所在的进程。SurfaceControl的构造函数可以看出,SurfaceControl的主要成员变量由CreateSurfaceResult提供,比如CreateSurfaceResult.handle,CreateSurfaceResult.layerId等,通过mClient->createSurface创建完成之后,最终创建了 C++ 层的SurfaceControl,并返回给 Java 层。所以这里重点关注mClient->createSurface的实现。
Layer 创建
rust
binder::Status Client::createSurface(const std::string& name, int32_t flags,
const sp<IBinder>& parent, const gui::LayerMetadata& metadata,
gui::CreateSurfaceResult* outResult) {
...
const status_t status = mFlinger->createLayer(args, *outResult);
return binderStatusFromStatusT(status);
}
这里的 mFlinger 指的就是 SurfaceFlinger
ini
status_t SurfaceFlinger::createLayer(LayerCreationArgs& args, gui::CreateSurfaceResult& outResult) {
status_t result = NO_ERROR;
// 声明一个 Layer
sp<Layer> layer;
switch (args.flags & ISurfaceComposerClient::eFXSurfaceMask) {
...
// 创建一块 Layer
result = createBufferStateLayer(args, &outResult.handle, &layer);
} break;
}
...
outResult.transformHint = static_cast<int32_t>(outTransformHint);
outResult.layerId = layer->sequence;
outResult.layerName = String16(layer->getDebugName());
return result;
}
这里我们重点看一下 createBufferStateLayer 的实现
scss
status_t SurfaceFlinger::createBufferStateLayer(LayerCreationArgs& args, sp<IBinder>* handle,
sp<Layer>* outLayer) {
// getFactory() 返回的是 DefaultFactory
*outLayer = getFactory().createBufferStateLayer(args);
// 把 Layer Handle 交给 outResult.handle,也就是 CreateSurfaceResult.handle
// CreateSurfaceResult.handle 最终会作为 SurfaceControl 构造函数的参数传递给 SurfaceControl
*handle = (*outLayer)->getHandle();
}
sp<Layer> DefaultFactory::createBufferStateLayer(const LayerCreationArgs& args) {
return sp<Layer>::make(args);
}
这里总结一下:
Client::createSurface最终会在 SurfaceFlinger 这边创建一块 Layer 对象- 把
LayerHandle赋给CreateSurfaceResult.handle,最终传给SurfaceControlLayerHandle是什么呢?LayerHandle本质上是一个BBinder,提供了getLayer等实现
arduino
class LayerHandle : public BBinder {
public:
LayerHandle(const sp<android::SurfaceFlinger>& flinger, const sp<android::Layer>& layer);
static sp<LayerHandle> fromIBinder(const sp<IBinder>& handle);
static sp<android::Layer> getLayer(const sp<IBinder>& handle);
static uint32_t getLayerId(const sp<IBinder>& handle);
...
private:
sp<android::SurfaceFlinger> mFlinger;
sp<android::Layer> mLayer;
const uint32_t mLayerId;
};
所以到这里,关于 SurfaceControl 和 Layer 的联系就很清晰了
SurfaceControl 和 Layer 是一一对应的关系,并且 SurfaceControl 间接持有 Layer,这意味着 SurfaceControl 能够控制 Layer。
到目前为止,SurfaceControl 和 Layer 的创建就已经完成了,但是今天的主角 Surface 并没有实际创建出来(我这里说的 Surface 指的是 C++ 层的 Surface,而不是 Java 层的 Surface), Surface 的真正创建发生在updateBlastSurfaceIfNeeded
Surface 创建
arduino
// frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
public int relayoutWindow(Session session, IWindow client, LayoutParams attrs,
int requestedWidth, int requestedHeight, int viewVisibility, int flags, int seq,
int lastSyncSeqId, WindowRelayoutResult outRelayoutResult) {
// 创建 SurfaceControl
result = createSurfaceControl(outSurfaceControl, result, win, winAnimator);
...
updateBlastSurfaceIfNeeded();
...
}
ini
void updateBlastSurfaceIfNeeded() {
...
blastSurface = mBlastBufferQueue.createSurface();
...
mSurface.transferFrom(blastSurface);
}
mBlastBufferQueue 是 BLASTBufferQueue,关于 BLASTBufferQueue 可以参考鄙人另外一篇文章,这里只做简单的介绍:
BLASTBufferQueue 由 "Producer" + "Comsumer" + BufferQueueCore,
- Producer 申请
GraphicBuffer,绘制 UI 到GraphicBuffer; - Comsumer 可以消费
GraphicBuffer,并且把GraphicBuffer提交到SurfaceFlinger - BufferQueueCore 队列负责管理 GraphicBuffer 在 Producer 和 Comsumer 之间的移动。
通过 BLASTBufferQueue 的 createSurface 来创建一个 blastSurface,然后把这个 blastSurface 赋给 ViewRootImpl 的 mSurface。接下来我们分析 BLASTBufferQueue.createSurface 的实现
kotlin
// frameworks/base/graphics/java/android/graphics/BLASTBufferQueue.java
public Surface createSurface() {
// nativeGetSurface 是一个 native 方法
return nativeGetSurface(mNativeObject, false /* includeSurfaceControlHandle */);
}
// frameworks/base/core/jni/android_graphics_BLASTBufferQueue.cpp
static jobject nativeGetSurface(JNIEnv* env, jclass clazz, jlong ptr,
jboolean includeSurfaceControlHandle) {
sp<BLASTBufferQueue> queue = reinterpret_cast<BLASTBufferQueue*>(ptr);
return android_view_Surface_createFromSurface(env,
queue->getSurface(includeSurfaceControlHandle));
}
这里最终会调用 BLASTBufferQueue.cpp 的 getSurface 方法
arduino
sp<Surface> BLASTBufferQueue::getSurface(bool includeSurfaceControlHandle) {
std::lock_guard _lock{mMutex};
sp<IBinder> scHandle = nullptr;
if (includeSurfaceControlHandle && mSurfaceControl) {
// scHandle 指的就是 LayerHandle
scHandle = mSurfaceControl->getHandle();
}
return sp<BBQSurface>::make(mProducer, true, scHandle, this);
}
- 在这里真正创建了
BBQSurface,BBQSurface是Surface的子类,并且把BLASTBufferQueue的mProducer作为构造函数的参数传给了BBQSurface/Surface,这就意味着BBQSurface/Surface能通过mProducer来申请GraphicBuffer来进行绘制,并把绘制好的 Buffer 插入BLASTBufferQueue,由 Comsumer 进行消费 - 从代码里面也可以看出 Surface 和 SurfaceControl 以及 Layer 之间的关系: Surface 通过 SurfaceControl 间接持有 Layer
到这里 native 层的 Surface 终于创建完成了, 并返回给 ViewRootImpl。