一、逻辑链路全景图

下面,我们逐层分析相关问题点
**#### 二、应用层(Java)
2.1 View绘制流程
-
关键类:
ViewRootImpl
:管理View树,触发VSync信号SurfaceHolder
:封装Surface的访问接口Choreographer
:协调VSync与绘制帧
-
流程:
View.invalidate()
触发重绘ViewRootImpl
注册VSync回调Choreographer
接收VSync信号- 调用
ViewRootImpl.doTraversal()
执行测量/布局/绘制
frameworks/base/core/java/android/view/ViewRootImpl.java
scss
` @UnsupportedAppUsage
void invalidate() {
mDirty.set(0, 0, mWidth, mHeight);
if (!mWillDrawSoon) {
scheduleTraversals();
}
}
void invalidateWorld(View view) {
view.invalidate();
if (view instanceof ViewGroup) {
ViewGroup parent = (ViewGroup) view;
for (int i = 0; i < parent.getChildCount(); i++) {
invalidateWorld(parent.getChildAt(i));
}
}
}
@Override
public void invalidateChild(View child, Rect dirty) {
invalidateChildInParent(null, dirty);
}
@Override
public ViewParent invalidateChildInParent(int[] location, Rect dirty) {
checkThread();
if (DEBUG_DRAW) Log.v(mTag, "Invalidate child: " + dirty);
if (dirty == null) {
invalidate();
return null;
} else if (dirty.isEmpty() && !mIsAnimating) {
return null;
}
if (mCurScrollY != 0 || mTranslator != null) {
mTempRect.set(dirty);
dirty = mTempRect;
if (mCurScrollY != 0) {
dirty.offset(0, -mCurScrollY);
}
if (mTranslator != null) {
mTranslator.translateRectInAppWindowToScreen(dirty);
}
if (mAttachInfo.mScalingRequired) {
dirty.inset(-1, -1);
}
}
invalidateRectOnScreen(dirty);
return null;
}
private void invalidateRectOnScreen(Rect dirty) {
if (DEBUG_DRAW) Log.v(mTag, "invalidateRectOnScreen: " + dirty);
final Rect localDirty = mDirty;
// Add the new dirty rect to the current one
localDirty.union(dirty.left, dirty.top, dirty.right, dirty.bottom);
// Intersect with the bounds of the window to skip
// updates that lie outside of the visible region
final float appScale = mAttachInfo.mApplicationScale;
final boolean intersected = localDirty.intersect(0, 0,
(int) (mWidth * appScale + 0.5f), (int) (mHeight * appScale + 0.5f));
if (!intersected) {
localDirty.setEmpty();
}
if (!mWillDrawSoon && (intersected || mIsAnimating)) {
scheduleTraversals();
}
}`
注册回调
scss
`
private void registerCallbacksForSync(boolean syncBuffer,
final SurfaceSyncGroup surfaceSyncGroup) {
if (!isHardwareEnabled()) {
return;
}
if (DEBUG_BLAST) {
Log.d(mTag, "registerCallbacksForSync syncBuffer=" + syncBuffer);
}
final Transaction t;
if (mHasPendingTransactions) {
t = new Transaction();
t.merge(mPendingTransaction);
mHasPendingTransactions = false;
} else {
t = null;
}
mAttachInfo.mThreadedRenderer.registerRtFrameCallback(new FrameDrawingCallback() {
@Override
public void onFrameDraw(long frame) {
}
@Override
public HardwareRenderer.FrameCommitCallback onFrameDraw(int syncResult, long frame) {
if (DEBUG_BLAST) {
Log.d(mTag,
"Received frameDrawingCallback syncResult=" + syncResult + " frameNum="
+ frame + ".");
}
if (t != null) {
mergeWithNextTransaction(t, frame);
}
// If the syncResults are SYNC_LOST_SURFACE_REWARD_IF_FOUND or
// SYNC_CONTEXT_IS_STOPPED it means nothing will draw. There's no need to set up
// any blast sync or commit callback, and the code should directly call
// pendingDrawFinished.
if ((syncResult
& (SYNC_LOST_SURFACE_REWARD_IF_FOUND | SYNC_CONTEXT_IS_STOPPED)) != 0) {
surfaceSyncGroup.addTransaction(
mBlastBufferQueue.gatherPendingTransactions(frame));
surfaceSyncGroup.markSyncReady();
return null;
}
if (DEBUG_BLAST) {
Log.d(mTag, "Setting up sync and frameCommitCallback");
}
if (syncBuffer) {
boolean result = mBlastBufferQueue.syncNextTransaction(transaction -> {
Runnable timeoutRunnable = () -> Log.e(mTag,
"Failed to submit the sync transaction after 4s. Likely to ANR "
+ "soon");
mHandler.postDelayed(timeoutRunnable, 4000L * Build.HW_TIMEOUT_MULTIPLIER);
transaction.addTransactionCommittedListener(mSimpleExecutor,
() -> mHandler.removeCallbacks(timeoutRunnable));
surfaceSyncGroup.addTransaction(transaction);
surfaceSyncGroup.markSyncReady();
});
if (!result) {
// syncNextTransaction can only return false if something is already trying
// to sync the same frame in the same BBQ. That shouldn't be possible, but
// if it did happen, invoke markSyncReady so the active SSG doesn't get
// stuck.
Log.w(mTag, "Unable to syncNextTransaction. Possibly something else is"
+ " trying to sync?");
surfaceSyncGroup.markSyncReady();
}
}
return didProduceBuffer -> {
if (DEBUG_BLAST) {
Log.d(mTag, "Received frameCommittedCallback"
+ " lastAttemptedDrawFrameNum=" + frame
+ " didProduceBuffer=" + didProduceBuffer);
}
// If frame wasn't drawn, clear out the next transaction so it doesn't affect
// the next draw attempt. The next transaction and transaction complete callback
// were only set for the current draw attempt.
if (!didProduceBuffer) {
mBlastBufferQueue.clearSyncTransaction();
// Gather the transactions that were sent to mergeWithNextTransaction
// since the frame didn't draw on this vsync. It's possible the frame will
// draw later, but it's better to not be sync than to block on a frame that
// may never come.
surfaceSyncGroup.addTransaction(
mBlastBufferQueue.gatherPendingTransactions(frame));
surfaceSyncGroup.markSyncReady();
return;
}
// If we didn't request to sync a buffer, then we won't get the
// syncNextTransaction callback. Instead, just report back to the Syncer so it
// knows that this sync request is complete.
if (!syncBuffer) {
surfaceSyncGroup.markSyncReady();
}
};
}
});
}`
测量布局计算
ini
` void doTraversal() {
if (mTraversalScheduled) {
mTraversalScheduled = false;
mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
if (mProfile) {
Debug.startMethodTracing("ViewAncestor");
}
performTraversals();
if (mProfile) {
Debug.stopMethodTracing();
mProfile = false;
}
}
}`
Choreographer 接收 VSync 信号
less
` /**
* Posts a vsync callback to run on the next frame.
* <p>
* The callback runs once then is automatically removed.
* </p>
*
* @param callback The vsync callback to run during the next frame.
*
* @see #removeVsyncCallback
*/
public void postVsyncCallback(@NonNull VsyncCallback callback) {
if (callback == null) {
throw new IllegalArgumentException("callback must not be null");
}
postCallbackDelayedInternal(CALLBACK_ANIMATION, callback, VSYNC_CALLBACK_TOKEN, 0);
} `
测量结束之后,进入surface创建阶段

代码体现:
WindowManagerService

WIndowState
csharp
`void attach() {
if (DEBUG) Slog.v(TAG, "Attaching " + this + " token=" + mToken);
mSession.windowAddedLocked();
}`
Session
ini
` void windowAddedLocked() {
if (mPackageName == null) {
mPackageName = mProcess.mInfo.packageName;
mRelayoutTag = "relayoutWindow: " + mPackageName;
}
if (mSurfaceSession == null) {
if (DEBUG) {
Slog.v(TAG_WM, "First window added to " + this + ", creating SurfaceSession");
}
mSurfaceSession = new SurfaceSession();
ProtoLog.i(WM_SHOW_TRANSACTIONS, " NEW SURFACE SESSION %s", mSurfaceSession);
mService.mSessions.add(this);
if (mLastReportedAnimatorScale != mService.getCurrentAnimatorScale()) {
mService.dispatchNewAnimatorScaleLocked(this);
}
}
mNumWindow++;
}`
三、JNI桥接层
3.1 Native方法绑定
- Session 创建
android_view_SurfaceSession.cpp
scss
static jlong nativeCreate(JNIEnv* env, jclass clazz) {
SurfaceComposerClient* client = new SurfaceComposerClient();
client->incStrong((void*)nativeCreate);
return reinterpret_cast<jlong>(client);
}
SurfaceComposerClient内做的事情是什么呢?

最终通过使用reinterpret_cast将指向刚刚创建的SurfaceComposerClient对象的指针转换为一个整型返回给上层的SurfaceSession。
同样的创建Surface的还有 android_view_Surface.cpp 和 android_view_SurfaceControl.cpp
关键方法和代码如下:

scss
static jlong nativeLockCanvas(JNIEnv* env, jclass clazz,
jlong nativeObject, jobject canvasObj, jobject dirtyRectObj) {
sp<Surface> surface(reinterpret_cast<Surface *>(nativeObject));
if (!isSurfaceValid(surface)) {
jniThrowException(env, IllegalArgumentException, NULL);
return 0;
}
if (!ACanvas_isSupportedPixelFormat(ANativeWindow_getFormat(surface.get()))) {
native_window_set_buffers_format(surface.get(), PIXEL_FORMAT_RGBA_8888);
}
Rect dirtyRect(Rect::EMPTY_RECT);
Rect* dirtyRectPtr = NULL;
if (dirtyRectObj) {
dirtyRect.left = env->GetIntField(dirtyRectObj, gRectClassInfo.left);
dirtyRect.top = env->GetIntField(dirtyRectObj, gRectClassInfo.top);
dirtyRect.right = env->GetIntField(dirtyRectObj, gRectClassInfo.right);
dirtyRect.bottom = env->GetIntField(dirtyRectObj, gRectClassInfo.bottom);
dirtyRectPtr = &dirtyRect;
}
ANativeWindow_Buffer buffer;
status_t err = surface->lock(&buffer, dirtyRectPtr);
if (err < 0) {
const char* const exception = (err == NO_MEMORY) ?
OutOfResourcesException : IllegalArgumentException;
jniThrowException(env, exception, NULL);
return 0;
}
graphics::Canvas canvas(env, canvasObj);
canvas.setBuffer(&buffer, static_cast<int32_t>(surface->getBuffersDataSpace()));
if (dirtyRectPtr) {
canvas.clipRect({dirtyRect.left, dirtyRect.top, dirtyRect.right, dirtyRect.bottom});
}
if (dirtyRectObj) {
env->SetIntField(dirtyRectObj, gRectClassInfo.left, dirtyRect.left);
env->SetIntField(dirtyRectObj, gRectClassInfo.top, dirtyRect.top);
env->SetIntField(dirtyRectObj, gRectClassInfo.right, dirtyRect.right);
env->SetIntField(dirtyRectObj, gRectClassInfo.bottom, dirtyRect.bottom);
}
// Create another reference to the surface and return it. This reference
// should be passed to nativeUnlockCanvasAndPost in place of mNativeObject,
// because the latter could be replaced while the surface is locked.
sp<Surface> lockedSurface(surface);
lockedSurface->incStrong(&sRefBaseOwner);
return (jlong) lockedSurface.get();
}

ini
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;
if (sessionObj != NULL) {
client = android_view_SurfaceSession_getClient(env, sessionObj);
} else {
client = SurfaceComposerClient::getDefault();
}
SurfaceControl *parent = reinterpret_cast<SurfaceControl*>(parentObject);
sp<SurfaceControl> surface;
LayerMetadata metadata;
Parcel* parcel = parcelForJavaObject(env, metadataParcel);
if (parcel && !parcel->objectsCount()) {
status_t err = metadata.readFromParcel(parcel);
if (err != NO_ERROR) {
jniThrowException(env, "java/lang/IllegalArgumentException",
"Metadata parcel has wrong format");
}
}
sp<IBinder> parentHandle;
if (parent != nullptr) {
parentHandle = parent->getHandle();
}
status_t err = client->createSurfaceChecked(String8(name.c_str()), w, h, format, &surface,
flags, parentHandle, std::move(metadata));
if (err == NAME_NOT_FOUND) {
jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
return 0;
} else if (err != NO_ERROR) {
jniThrowException(env, OutOfResourcesException, statusToString(err).c_str());
return 0;
}
surface->incStrong((void *)nativeCreate);
return reinterpret_cast<jlong>(surface.get());
}
衔接层,就不详细解释了,其目的是将c++层的逻暴露给java层。那接下来,我们看一下c++层,surfaceFlinger是如何操作的
四、SurfaceFlinger服务端(C++)
1.1入口代码:
frameworks/native/services/surfaceflinger/main_surfaceflinger.cpp
关键代码如下:
scss
`int main(int argc, char** argv) {
// 初始化Binder线程池(最大4线程)
hardware::configureRpcThreadpool(1, false);
ProcessState::self()->setThreadPoolMaxThreadCount(4);
// 创建SurfaceFlinger实例
sp<SurfaceFlinger> flinger = surfaceflinger::createSurfaceFlinger();
// 设置进程优先级(URGENT_DISPLAY)
setpriority(PRIO_PROCESS, 0, PRIORITY_URGENT_DISPLAY);
set_sched_policy(0, SP_FOREGROUND);
// 注册到ServiceManager
sp<IServiceManager> sm = defaultServiceManager();
sm->addService(String16("SurfaceFlinger"), flinger, false, ...);
// 启动主循环
flinger->run();
return 0;
}`
核心作用:初始化Binder通信、创建SF实例、设置优先级、注册系统服务
1.2 SurfaceFlinger构造函数
frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
关键操作:
- 初始化成员变量(如
mPrimaryDisplay
、mHwc
、mEventQueue
)。 - 注册VSync事件监听器。
- 初始化硬件合成器(HWC)接口。
最关键的一步,在这里创建图层,即Layer的创建。
1.3 图层管理
Layer创建:
scss
`// frameworks/native/services/surfaceflinger/Layer.cpp
//简化版
Layer::Layer(const sp<SurfaceFlinger>& flinger)
: mFlinger(flinger), mBufferQueue(new BufferQueue()) {
mId = generateLayerId(); // 生成唯一ID
mFlinger->registerLayer(this); // 注册到LayerStack
}`
在Laye做图层管理的时候,最重要的是z-order算法管理:
scss
`// LayerStack.cpp
void LayerStack::sortLayers() {
std::sort(mLayers.begin(), mLayers.end(),
[](Layer* a, Layer* b) { return a->getZ() < b->getZ(); });
}`
当如上所有的全部做完之后,再次回到surfaceFlinger中进行合成,完成引擎合成
合成流程:
- 处理事务(Transaction)
- 计算可见区域(computeVisibleRegions)
- 执行合成(handlePageFlip)
- 提交到DisplayDevice
VSync处理
-
VSync信号接收:
arduino`// EventThread.cpp void EventThread::onVSyncReceived(int32_t sequenceId, nsecs_t timestamp) { mFlinger->onVSyncReceived(sequenceId, timestamp); }`
帧提交:
arduino
`// Choreographer.cpp
void Choreographer::postFrameCallback(const FrameCallback& callback) {
mFrameCallbacks.add(callback);
}`
如此完成服务层的逻辑,进入合成帧数处理和Vsync的信号处理之后,进入硬件抽象层
五、硬件抽象层(HAL)
1.HAL在SurfaceFlinger中的核心作用
硬件抽象层(HAL)是Android图形系统的关键组件,SurfaceFlinger通过HAL与底层显示硬件(如GPU、Display Controller)交互。其核心功能包括:
- 硬件加速合成:通过HWC(Hardware Composer)直接提交图层到硬件。
- 显示参数配置:设置分辨率、刷新率、色彩空间等。
- 事件通知:接收VSync、热插拔等硬件事件。
2、HWC交互流程详解
2.1 HWC初始化流程
-
服务发现
- SurfaceFlinger启动时,通过
hw_get_module(HWC_HARDWARE_MODULE_ID, ...)
加载HWC HAL模块。 - 代码路径:
services/gui/SurfaceFlinger.cpp
的init()
函数。
- SurfaceFlinger启动时,通过
-
创建HWC实例
scss`// frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp status_t SurfaceFlinger::init() { mHwc = getHwComposer(); if (mHwc == nullptr) { ALOGE("Failed to get HWC instance"); return NO_MEMORY; } mHwc->registerCallback(this); // 注册回调 }` **显示设备初始化**
-
通过HWC获取显示参数(如EDID信息):
scss`mHwc->getDisplayCapabilities(displayId, &capabilities); mHwc->getDisplayIdentificationData(displayId, &type, &data);` ##### **2.2 图层合成流程**
2.2.图层提交
- 1.SurfaceFlinger将图层信息(位置、透明度、缓冲区)封装为
hwc2_layer_t
,调用mHwc->setLayerBuffer()
提交。
arduino
`// frameworks/native/services/surfaceflinger/HWComposer.cpp
arduino
status_t HWComposer::setLayerBuffer(hwc2_layer_t layer,
const sp<GraphicBuffer>& buffer) {
// 调用HWC HAL的setLayerBuffer接口
return mHwc->setLayerBuffer(displayId, layer, buffer);
}`
-
2.合成策略决策
-
HWC根据图层属性(如是否支持硬件合成)返回合成类型:
arduino`// HWC回调函数 void HWComposer::onLayerSubmitted(hwc2_layer_t layer, const sp<GraphicBuffer>& buffer) { if (buffer->hasProtectedContent()) { mHwc->setLayerSurfaceDamage(layer, damageRegion); } }`
硬件合成执行
-
HWC调用底层驱动(如DRM/KMS)提交合成结果:
arduino`// vendor/qcom/opensource/display-hal/hwc2/ComposerEngine.cpp bool ComposerEngine::presentDisplay(hwc2_display_t display) { mDrmManager.commitFrame(display); // DRM提交帧缓冲区 return true; }`
2.3 回退机制(Fallback)
当HWC无法处理时(如复杂混合模式),SurfaceFlinger切换至软件合成:
-
标记回退图层
arduino`// frameworks/native/services/surfaceflinger/HWComposer.cpp void HWComposer::determineCompositionType() { if (mHwc->needsClientComposition(displayId)) { mCompositionType = CompositionType::Client; // 回退到SF合成 } }`
OpenGL合成
-
通过RenderEngine执行GPU渲染:
arduino`// frameworks/native/services/surfaceflinger/RenderEngine.cpp void RenderEngine::drawLayers(const std::vector<Layer>& layers) { glUseProgram(mProgram); for (auto& layer : layers) { glBindTexture(GL_TEXTURE_2D, layer.buffer->getNativeBuffer()->handle); // 执行几何变换与混合 } }`
3、HWC与SurfaceFlinger的深度协作
3.1 事件通知机制
-
VSync信号传递
-
HWC通过回调通知SurfaceFlinger垂直同步事件:
arduino`// frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp void SurfaceFlinger::onVSyncReceived(hwc2_display_t display, nsecs_t timestamp) { mEventQueue->invalidate(); // 触发合成 }`
-
2.热插拔处理
-
当显示器连接/断开时,HWC触发回调:
php`// frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp void HWComposer::registerCallback(ISurfaceComposer::VsyncSource vsyncSource, ISurfaceComposerCallback* callbacks) { mHwc->registerCallback(vsyncSource, callbacks); }`
3.2 内存管理
-
Gralloc缓冲区分配
-
HWC通过
gralloc
模块分配图形内存:arduino`// frameworks/native/services/surfaceflinger/GraphicBuffer.cpp sp<GraphicBuffer> GraphicBuffer::alloc(size_t w, size_t h, PixelFormat format) { hw_module_t* module; hw_get_module(GRALLOC_HARDWARE_MODULE_ID, (hw_module_t**)&module); return static_cast<alloc_device_t*>(module->methods->open(module, GRALLOC_HARDWARE_MODULE_ID))->alloc(w, h, format); }`
-
3.3 多显示器支持
-
虚拟显示创建
arduino`// frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp sp<IBinder> SurfaceFlinger::createDisplay(const String8& displayName, bool secure) { sp<DisplayDevice> display = new DisplayDevice(this, displayName, secure); mHwc->createVirtualDisplay(displayId, width, height, &display->getHandle()); return display; }`
如上流程,大概是surfaceFlinger的合成全流程,接下来就是验证测试的时刻。
4、调试与验证方法
4.1 日志分析
csharp
# 查看HWC合成日志
adb logcat | grep -E "HWC|SurfaceFlinger"
# 示例输出:
I/SurfaceFlinger( 1234): Layer 0x7f8e5a0000 (com.android.systemui) is hardware composed
4.2 Perfetto跟踪
ini
# 启动Perfetto捕获HWC事件
adb shell perfetto --config=android.surfaceflinger --out=surfacetrace.perfetto
4.3 代码验证点
关键流程 | 验证文件/函数 | 作用 |
---|---|---|
HWC初始化 | SurfaceFlinger::init() |
加载HWC模块并注册回调 |
图层提交 | HWComposer::setLayerBuffer() |
传递图层缓冲区到硬件 |
合成策略决策 | HWComposer::determineCompositionType() |
判断是否启用硬件合成 |
DRM提交帧 | ComposerEngine::presentDisplay() |
通过DRM/KMS提交最终帧 |
5、典型问题排查流程
问题:某应用界面显示异常(黑屏/撕裂)
-
检查HWC日志
perl
adb logcat | grep "HWC error"
-
若出现
HWC: Failed to present display
,可能为硬件驱动问题。 -
验证图层合成类型
less
// 在HWComposer.cpp中添加调试输出
ALOGD("Layer %p: Composition type %d", layer, mHwc->getCompositionType(displayId));
-
若返回
CLIENT
,说明回退到软件合成。 -
检查BufferQueue状态
css
adb shell dumpsys SurfaceFlinger --latency
- 查看
BufferQueue: mActiveBufferCount
是否正常。