android freeze,Android

本文详细解析了Android系统中的SurfaceFlinger服务,它负责管理显示层的混合与帧缓冲的更新。SurfaceFlinger通过Binder与客户端通信,并继承Thread类实现循环执行。文章介绍了SurfaceFlinger的工作流程,包括等待重绘消息、处理页面翻转、计算和绘制各Layer、解锁客户端以及提交帧缓冲到屏幕的过程,深入理解了Android图形系统的关键组件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

SurfaceFlinger 属于system_server进程,在system_init.cpp中利用SurfaceFlinger::instantiate()启动,在此加入到service manager中,所以本身提供service服务功能。

首先看下SurfaceFlinger的类声明:

class SurfaceFlinger :

public BinderService,

public BnSurfaceComposer,

protected Thread

从接口可以看出使用Binder与客户端通讯,并且继承线程 Thread 类,则循环执行threadLoop。完成系统中的各个Layer-Surface进行混合,然后将一帧帧混合好的图像传送到显示framebuffer中。

其主线程工作流程图如下:

25697300_1.gif

下面就这以上图五步将代码一一过一遍:

1、waitForEvent() 等待什么事情呢?

void SurfaceFlinger::waitForEvent()

{

while (true) {

......

sp msg = mEventQueue.waitMessage(timeout);

......

if (msg != 0) {

switch (msg->what) {

//等的就是这个消息事件哟。。。。

case MessageQueue::INVALIDATE:

// invalidate message, just return to the main loop

return;

}

}

}

}

原来是等待收到MessageQueue::INVALIDATE重绘消息才退回到主线程,那么这个消息由谁来发送呢?

请看下面代码:

void SurfaceFlinger::signalEvent() {

mEventQueue.invalidate();

}

void SurfaceFlinger::signal() const {

// this is the IPC call

const_cast(this)->signalEvent();

}

这是就是发送消息的点,这个函数signalEvent由谁来调用呢?其个这个发起都是上一节说的,在释放Surface对应的显示缓冲区需要显示时调用:

unlockAndPost() --> queueBuffer() --> mClient.signalServer() --> SurfaceFlinger::signal()

2、handlePageFlip()

该阶段会遍历各个Layer,在每个Layer中,取得并锁住该Layer的frontBuffer,然后利用frontBuffer 中的图像数据生成该Layer的2D贴图(Texture),并且计算更新区域,为后续的混合操作做准备。

void SurfaceFlinger::handlePageFlip()

{

//调用 lockPageFlip

visibleRegions |= lockPageFlip(currentLayers);

//取得屏幕的区域

const Region screenRegion(hw.bounds());

if (visibleRegions) {

Region opaqueRegion;

computeVisibleRegions(currentLayers, mDirtyRegion, opaqueRegion);

.....

mWormholeRegion = screenRegion.subtract(opaqueRegion);

}

.....

//调用 unlockPageFlip

unlockPageFlip(currentLayers);

}

上面的调用实际上是一对函数:lockPageFlip & lockPageFlip,那么主要干些啥呢?

bool SurfaceFlinger::lockPageFlip(const LayerVector& currentLayers)

{

bool recomputeVisibleRegions = false;

size_t count = currentLayers.size();

sp const* layers = currentLayers.array();

//逐个 layer 进行处理

for (size_t i=0 ; i

const sp& layer(layers[i]);

layer->lockPageFlip(recomputeVisibleRegions);

}

return recomputeVisibleRegions;

}

void Layer::lockPageFlip(bool& recomputeVisibleRegions)

{

SharedBufferServer* lcblk(sharedClient.get());

// 获取当前可用的 frontbuffer 索引号

ssize_t buf = lcblk->retireAndLock();

// 计算当前的脏区域

sp newFrontBuffer(getBuffer(buf));

if (newFrontBuffer != NULL) {

// get the dirty region

// compute the posted region

const Region dirty(lcblk->getDirtyRegion(buf));

mPostedDirtyRegion = dirty.intersect( newFrontBuffer->getBounds() );

....

// 如果有脏区域需要重绘,则生成 OpenGL ES 纹理贴图

reloadTexture( mPostedDirtyRegion );

}

void SurfaceFlinger::unlockPageFlip(const LayerVector& currentLayers)

{

const GraphicPlane& plane(graphicPlane(0));

const Transform& planeTransform(plane.transform());

size_t count = currentLayers.size();

sp const* layers = currentLayers.array();

for (size_t i=0 ; i

const sp& layer(layers[i]);

//进行区域的清理工作

layer->unlockPageFlip(planeTransform, mDirtyRegion);

}

}

void Layer::unlockPageFlip(

const Transform& planeTransform, Region& outDirtyRegion)

{

Region dirtyRegion(mPostedDirtyRegion);

if (!dirtyRegion.isEmpty()) {

mPostedDirtyRegion.clear();

....

if (visibleRegionScreen.isEmpty()) {

// an invisible layer should not hold a freeze-lock

// (because it may never be updated and therefore never release it)

mFreezeLock.clear();

}

}

以上的工作就是按照 Zorder 序计算自已屏幕上的可显示区域:

1、以自己的W,H给出自己初始的可见区域

2、减去自己上面窗口所覆盖的区域

25697300_2.gif

3、handleRepaint

每个Layer的数据都准备好了,并且各个脏区域也计算ok,下步就是根据 Zorder 序从底部将数据绘制到主Surface上

void SurfaceFlinger::handleRepaint()

{

// compute the invalid region

mInvalidRegion.orSelf(mDirtyRegion);

....

// compose all surfaces

composeSurfaces(mDirtyRegion);

// clear the dirty regions

mDirtyRegion.clear();

}

void SurfaceFlinger::composeSurfaces(const Region& dirty)

{

...

const size_t count = layers.size();

for (size_t i=0 ; i

const sp& layer(layers[i]);

const Region clip(dirty.intersect(layer->visibleRegionScreen));

if (!clip.isEmpty()) {

// 这就是绘图核心函数

layer->draw(clip);

}

}

}

void Layer::onDraw(const Region& clip) const

---> drawWithOpenGL(clip, tex); 基本上都是OpenGL ES 操作函数

while (it != end) {

const Rect& r = *it++;

const GLint sy = fbHeight - (r.top + r.height());

// 裁剪

glScissor(r.left, sy, r.width(), r.height());

// 画矩形

glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

}4、unlockClients()

释放 handlePageFlip 占用的 frontbuffer 索引号,以便客户端可以继续在新的surface画图

void SurfaceFlinger::unlockClients()

{

...

for (size_t i=0 ; i

const sp& layer = layers[i];

layer->finishPageFlip();

}

}

-->

SharedBufferServer* lcblk(sharedClient.get());

status_t err = lcblk->unlock( buf );

5、postFramebuffer()

现在已经将所有的Layer图层数据合成完成,最后就是输入到屏幕上显示了

void SurfaceFlinger::postFramebuffer()

{

//调用此函数将混合后的图像传递到屏幕中进行显示

hw.flip(mInvalidRegion);

...

}

void DisplayHardware::flip(const Region& dirty) const

{

// 显示图像吧。。。。。

eglSwapBuffers(dpy, surface);

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值