您的位置:首页 > 产品设计 > UI/UE

Android GUI更新过程

2013-12-19 14:32 357 查看
转载时请注明出处和作者联系方式

文章出处:http://www.limodev.cn/blog

作者联系方式:李先静 <xianjimli@gmail.com>

Android GUI更新过程

相关组件



1.ViewRoot

在private void draw(boolean fullRedrawNeeded)中,会调用lockCanvas,从而获取一个Canvas对象,然后调用递归调用子窗口(View)的draw函数 去绘制自己,最后调用unlockCanvasAndPost让Surface把自己更新到屏幕上。

[c] view
plaincopy

canvas <span style="color: #339933;">=</span>

surface.<span style="color: #202020;">lockCanvas</span>

<span style="color: #009900;">(</span>

dirty<span style="color: #009900;">)</span>

<span style="color: #339933;">;</span>

mView.<span style="color: #202020;">draw</span>

<span style="color: #009900;">(</span>

canvas<span style="color: #009900;">)</span>

<span style="color: #339933;">;</span>

surface.<span style="color: #202020;">unlockCanvasAndPost</span>

<span style="color: #009900;">(</span>

canvas<span style="color: #009900;">)</span>

<span style="color: #339933;">;</span>

2.android/view/Surface

它主要对一些native函数的包装。

[c] view
plaincopy

private native Canvas lockCanvasNative<span style="color: #009900;">(</span>

Rect dirty<span style="color: #009900;">)</span>

<span style="color: #339933;">;</span>

public native <span style="color: #993333;">void</span>

unlockCanvasAndPost<span style="color: #009900;">(</span>

Canvas canvas<span style="color: #009900;">)</span>

<span style="color: #339933;">;</span>

3.android_view_Surface.cpp

这是native函数的实现。

Surface_lockCanvas它先锁住Surface,从而获取Surface相关的信息,如果格式、宽度、高度和像素缓冲区。然后创建一个bitmap,这个bitmap和共享一个像素缓冲区,这样View就能直接把自己绘制到Surface上了。

[c] view
plaincopy

status_t err <span style="color: #339933;">=</span>

surface<span style="color: #339933;">-></span>

lock<span style="color: #009900;">(</span>

<span style="color: #339933;">&</span>

info<span style="color: #339933;">,</span>

<span style="color: #339933;">&</span>

dirtyRegion<span style="color: #009900;">)</span>

<span style="color: #339933;">;</span>

bitmap.<span style="color: #202020;">setPixels</span>

<span style="color: #009900;">(</span>

info.<span style="color: #202020;">bits</span>

<span style="color: #009900;">)</span>

<span style="color: #339933;">;</span>

nativeCanvas<span style="color: #339933;">-></span>

setBitmapDevice<span style="color: #009900;">(</span>

bitmap<span style="color: #009900;">)</span>

<span style="color: #339933;">;</span>

Surface_unlockCanvasAndPost它断开SkCanvas与Surface之间的关系,然后调用Surface的unlockAndPost。

[c] view
plaincopy

nativeCanvas<span style="color: #339933;">-></span>

setBitmapDevice<span style="color: #009900;">(</span>

SkBitmap<span style="color: #009900;">(</span>

<span style="color: #009900;">)</span>

<span style="color: #009900;">)</span>

<span style="color: #339933;">;</span>

status_t err <span style="color: #339933;">=</span>

surface<span style="color: #339933;">-></span>

unlockAndPost<span style="color: #009900;">(</span>

<span style="color: #009900;">)</span>

<span style="color: #339933;">;</span>

4.surfaceflinger_client/Surface.cpp

Surface::lock调用dequeueBuffer获取一个可用的Buffer,dequeueBuffer会调用SharedBufferClient::dequeue等到backbuffer可用,然后锁住这个Buffer并填充相关信息。

[c] view
plaincopy

status_t err <span style="color: #339933;">=</span>

dequeueBuffer<span style="color: #009900;">(</span>

<span style="color: #339933;">&</span>

backBuffer<span style="color: #009900;">)</span>

<span style="color: #339933;">;</span>

err <span style="color: #339933;">=</span>

lockBuffer<span style="color: #009900;">(</span>

backBuffer.<span style="color: #202020;">get</span>

<span style="color: #009900;">(</span>

<span style="color: #009900;">)</span>

<span style="color: #009900;">)</span>

<span style="color: #339933;">;</span>

Surface::unlockAndPost先unlock Buffer,然后调queueBuffer显示Buffer。

[c] view
plaincopy

status_t err <span style="color: #339933;">=</span>

mLockedBuffer<span style="color: #339933;">-></span>

unlock<span style="color: #009900;">(</span>

<span style="color: #009900;">)</span>

<span style="color: #339933;">;</span>

err <span style="color: #339933;">=</span>

queueBuffer<span style="color: #009900;">(</span>

mLockedBuffer.<span style="color: #202020;">get</span>

<span style="color: #009900;">(</span>

<span style="color: #009900;">)</span>

<span style="color: #009900;">)</span>

<span style="color: #339933;">;</span>

Surface::queueBuffer是比较有意思的,它设置更新的区域,然后通知服务端(SurfaceFlinger)。

[c] view
plaincopy

mSharedBufferClient<span style="color: #339933;">-></span>

setDirtyRegion<span style="color: #009900;">(</span>

bufIdx<span style="color: #339933;">,</span>

mDirtyRegion<span style="color: #009900;">)</span>

<span style="color: #339933;">;</span>

err <span style="color: #339933;">=</span>

mSharedBufferClient<span style="color: #339933;">-></span>

queue<span style="color: #009900;">(</span>

bufIdx<span style="color: #009900;">)</span>

<span style="color: #339933;">;</span>

client<span style="color: #339933;">-></span>

signalServer<span style="color: #009900;">(</span>

<span style="color: #009900;">)</span>

<span style="color: #339933;">;</span>

通过binder发送请求给服务:

[c] view
plaincopy

virtual <span style="color: #993333;">void</span>

signal<span style="color: #009900;">(</span>

<span style="color: #009900;">)</span>

<span style="color: #993333;">const</span>

<span style="color: #009900;">{</span>

Parcel data<span style="color: #339933;">,</span>

reply<span style="color: #339933;">;</span>

data.<span style="color: #202020;">writeInterfaceToken</span>

<span style="color: #009900;">(</span>

ISurfaceComposer<span style="color: #339933;">::</span>

<span style="color: #202020;">getInterfaceDescriptor</span>

<span style="color: #009900;">(</span>

<span style="color: #009900;">)</span>

<span style="color: #009900;">)</span>

<span style="color: #339933;">;</span>

remote<span style="color: #009900;">(</span>

<span style="color: #009900;">)</span>

<span style="color: #339933;">-></span>

transact<span style="color: #009900;">(</span>

BnSurfaceComposer<span style="color: #339933;">::</span>

<span style="color: #202020;">SIGNAL</span>

<span style="color: #339933;">,</span>

data<span style="color: #339933;">,</span>

<span style="color: #339933;">&</span>

reply<span style="color: #339933;">,</span>

IBinder<span style="color: #339933;">::</span>

<span style="color: #202020;">FLAG_ONEWAY</span>

<span style="color: #009900;">)</span>

<span style="color: #339933;">;</span>

<span style="color: #009900;">}</span>

5.SurfaceFlinger

[c] view
plaincopy

BnSurfaceComposer<span style="color: #339933;">::</span>

<span style="color: #202020;">onTransact</span>

<span style="color: #b1b100;">case</span>

SIGNAL<span style="color: #339933;">:</span>

<span style="color: #009900;">{</span>

CHECK_INTERFACE<span style="color: #009900;">(</span>

ISurfaceComposer<span style="color: #339933;">,</span>

data<span style="color: #339933;">,</span>

reply<span style="color: #009900;">)</span>

<span style="color: #339933;">;</span>

signal<span style="color: #009900;">(</span>

<span style="color: #009900;">)</span>

<span style="color: #339933;">;</span>

<span style="color: #009900;">}</span>

<span style="color: #000000; font-weight: bold;">break</span>

<span style="color: #339933;">;</span>

这是SurfaceFlinger中处理SIGNAL的代码,它调用SurfaceFlinger::signal,再调用 SurfaceFlinger::signalEvent,最后调用MessageQueue::invalidate唤醒是 SurfaceFlinger的主循环。

在主循环中waitForEvent返回,再handleRepaint去合成个Layer/Surface。

[c] view
plaincopy

bool SurfaceFlinger<span style="color: #339933;">::</span>

<span style="color: #202020;">threadLoop</span>

<span style="color: #009900;">(</span>

<span style="color: #009900;">)</span>

<span style="color: #009900;">{</span>

waitForEvent<span style="color: #009900;">(</span>

<span style="color: #009900;">)</span>

<span style="color: #339933;">;</span>

handleRepaint<span style="color: #009900;">(</span>

<span style="color: #009900;">)</span>

<span style="color: #339933;">;</span>

postFramebuffer<span style="color: #009900;">(</span>

<span style="color: #009900;">)</span>

<span style="color: #339933;">;</span>

<span style="color: #009900;">}</span>

SurfaceFlinger::handleRepaint会调用composeSurfaces把需要绘制各个Surface合并起来,绘制到FrameBuffer的BackBuffer上。

[c] view
plaincopy

<span style="color: #b1b100;">for</span>

<span style="color: #009900;">(</span>

size_t i<span style="color: #339933;">=</span>

<span style="color: #0000dd;">0</span>

<span style="color: #339933;">;</span>

i<span style="color: #339933;"><</span>

count <span style="color: #339933;">;</span>

<span style="color: #339933;">++</span>

i<span style="color: #009900;">)</span>

<span style="color: #009900;">{</span>

<span style="color: #993333;">const</span>

sp<span style="color: #339933;"><</span>

LayerBase<span style="color: #339933;">>&</span>

layer <span style="color: #339933;">=</span>

layers<span style="color: #009900;">[</span>

i<span style="color: #009900;">]</span>

<span style="color: #339933;">;</span>

<span style="color: #993333;">const</span>

Region<span style="color: #339933;">&</span>

visibleRegion<span style="color: #009900;">(</span>

layer<span style="color: #339933;">-></span>

visibleRegionScreen<span style="color: #009900;">)</span>

<span style="color: #339933;">;</span>

<span style="color: #b1b100;">if</span>

<span style="color: #009900;">(</span>

<span style="color: #339933;">!</span>

visibleRegion.<span style="color: #202020;">isEmpty</span>

<span style="color: #009900;">(</span>

<span style="color: #009900;">)</span>

<span style="color: #009900;">)</span>

<span style="color: #009900;">{</span>

<span style="color: #808080; font-style: italic;">/* broncho cy add */</span>

<span style="color: #339933;">#ifdef USEOVERLAY</span>

mToppest<span style="color: #009900;">[</span>

<span style="color: #0000dd;">1</span>

<span style="color: #009900;">]</span>

<span style="color: #339933;">=</span>

mToppest<span style="color: #009900;">[</span>

<span style="color: #0000dd;">0</span>

<span style="color: #009900;">]</span>

<span style="color: #339933;">;</span>

mToppest<span style="color: #009900;">[</span>

<span style="color: #0000dd;">0</span>

<span style="color: #009900;">]</span>

<span style="color: #339933;">=</span>

layer<span style="color: #339933;">-></span>

getIdentity<span style="color: #009900;">(</span>

<span style="color: #009900;">)</span>

<span style="color: #339933;">;</span>

<span style="color: #339933;">#endif</span>

<span style="color: #808080; font-style: italic;">/* broncho end */</span>

<span style="color: #993333;">const</span>

Region clip<span style="color: #009900;">(</span>

dirty.<span style="color: #202020;">intersect</span>

<span style="color: #009900;">(</span>

visibleRegion<span style="color: #009900;">)</span>

<span style="color: #009900;">)</span>

<span style="color: #339933;">;</span>

<span style="color: #b1b100;">if</span>

<span style="color: #009900;">(</span>

<span style="color: #339933;">!</span>

clip.<span style="color: #202020;">isEmpty</span>

<span style="color: #009900;">(</span>

<span style="color: #009900;">)</span>

<span style="color: #009900;">)</span>

<span style="color: #009900;">{</span>

layer<span style="color: #339933;">-></span>

draw<span style="color: #009900;">(</span>

clip<span style="color: #009900;">)</span>

<span style="color: #339933;">;</span>

<span style="color: #009900;">}</span>

<span style="color: #009900;">}</span>

<span style="color: #009900;">}</span>

SurfaceFlinger::postFramebuffer最后把FrameBuffer的BackBuffer显示到屏幕上:

[c] view
plaincopy

hw.<span style="color: #202020;">flip</span>

<span style="color: #009900;">(</span>

mInvalidRegion<span style="color: #009900;">)</span>

<span style="color: #339933;">;</span>

<span style="color: #339933;">--></span>

eglSwapBuffers<span style="color: #009900;">(</span>

dpy<span style="color: #339933;">,</span>

surface<span style="color: #009900;">)</span>

<span style="color: #339933;">;</span>

FrameBuffer具体的显示过程,下次再写吧。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: