这一路分析下来, 开始进入 JNI layer 了.
[android_view_SurfaceSession.cpp]
static jint nativeCreate(JNIEnv* env, jclass clazz) {
// new 一个 SurfaceComposerClient对象, 其功用后面会在分析.
sp<SurfaceComposerClient> client = new SurfaceComposerClient;
client->incStrong(clazz);
return reinterpret_cast<jint>(client);
}
到此在做个结论,handleResumeActivity 函数利用WindowManagerImpl依照WindowManager.LayoutParams的属性来为DecoreView增加一个 view的纪录.
, 在addView 过程会有以下的流程:
1. 产生一个新的ViewRootImpl, 在ViewRootImpl的对象初始化中建立一个 DecoreView 和 WindowManagerService 之间的 Session.
2. 将先前设置好的View 加入DecoreView. 在加入过程有两个关键动作如下:
a. 执行 performTraversals开始布局并且绘画显示画面.
b. SurfaceComposerClient 组件: new一个 SurfaceComposerClient对象, 其功用跟 surfaceControl 有关.
针对以上第二点的流程的两个关键动作,我们继续分析.
a. 执行 performTraversals
[ViewRootImpl.java]
private void performTraversals() {
// mView是前面经由setContentView的一个View,也就是DecoreView.
final View host = mView;
//...
//关键函数
relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
//....
//...
//开始绘图.
performDraw();
//...
}
performTraversals函数做蛮多杂事的, 我们只需要关心两个动作其中两个关键动作, relayoutWindow和 performDraw.
relayoutWindow 分析 | ||||
有此段程序代码,可以看到relayoutWindow函数会藉由Session去呼叫WindowManagerService的relayoutWindowfunction. 其中值得关注的是最后一个参数mSurface.这个mSurface是怎么来的.在定义 ViewRootImpl 类别一开始就产生了一个没有带参数的Surface物件 接这就继续分析WindowManagerService的relayoutWindow function做了哪些事? 由此段程序代码带出两个关键, Surface surface = winAnimator.createSurfaceLocked(); 和outSurface.copyFrom(surface); 就依序来分析这两个动作.
由此可知, winAnimator.createSurfaceLocked所做的事就是在native层产生一个SurfaceControl 对象,在Java层产生一个带有surfaceSession参数的Surface参考对象.
由以上的代码段,WindowManagerService的relayoutWindow可以做个以下总结: 1. 藉由mWindowMap里去得到目前Client (DecoreView)的WindowState对象. 2. 藉由此WindowState物件win来new一个带有SurfaceSession参数的Surface物件.用意是可以借着SurfaceComposerClient来新增一个SurfaceControl. 3. 利用Surface的copyfrom 函数把带有SurfaceSession参数的Surface对象复制一份到ViewRootImpl所产生的一个无参数建构出来的Surface对象. 结论又带出一个新的角色SurfaceComposerClient,其功用后面会分析. |
performDraw分析 |
[ViewRootImpl.java] 从以上的程序代码可以看到, Surface lock一块Canvas, 之前配置的View (DecoreView) 在利用这块Canvas来绘制UI组件.避免分析太分散,Surface的 lockCanvas, unlockCanvasAndPost和DecoreView的draw 函数分析放在最后分析. |
b.SurfaceComposerClient 组件.
当ViewRootImpl去设置View(DecoreView)时,会先经由Session通知WindowMangerService去addWindow, 在addWindow中会去new SurfaceSession.SurfaceComposerClient就是由new SurfaceSession中产生的.由于SurfaceComposerClient衍生自RefBase类别, 所以都会用sp来取得对象指针.
[android_view_SurfaceSession.cpp]
sp<SurfaceComposerClient> client = new SurfaceComposerClient;
通常利用sp来建构对象时,会先呼叫onFirstRef函数,才会呼叫相对应建构子.因此若想要看一下SurfaceComposerClient的初始实作, 需要从其onFirstRef函数下手,分析如下:
[SurfaceComposerClient.cpp]
void SurfaceComposerClient::onFirstRef() {
// ISurfaceComposer 是 surfaceFlinger的 binder界面,所以
//getComposerService会回传SurfaceFlinger的Binder Proxy:
//BpSurfaceComposer.
sp<ISurfaceComposer> sm(ComposerService::getComposerService());
if (sm != 0) {
sp<ISurfaceComposerClient> conn = sm->createConnection();
if (conn != 0) {
mClient = conn;
mStatus = NO_ERROR;
}
}
}
既然getComposerService回传的是SurfaceFlinger的Binder Proxy,表示由得到的对象,其方法可以在SurfaceFlnger类别去找.所以sm->createConnection(), 其createConnection函数如下所示:
[SurfaceFlinger.cpp]
sp<ISurfaceComposerClient> SurfaceFlinger::createConnection()
{
sp<ISurfaceComposerClient> bclient;
sp<Client> client(new Client(this));
status_t err = client->initCheck();
if (err == NO_ERROR) {
bclient = client;
}
return bclient;
}
createConnection 函数回传一个ISurfaceComposerClient指针对象, 其实作可以发现这个指针对象是一个Client的指针对象.接下来就来分析Client建构子和其方法initCheck.
[Client.cpp]
Client::Client(const sp<SurfaceFlinger>& flinger)
: mFlinger(flinger), mNameGenerator(1)
{
}
status_t Client::initCheck() const {
//没做任何事,推测未来会有实作.
return NO_ERROR;
}
c. lockCanvas, unlockCanvasAndPost
现在就来分析,Surface的 lockCanvas, unlockCanvasAndPost.
[Surface.java]
/** draw into a surface */
public Canvas lockCanvas(Rect dirty) throws OutOfResourcesException, IllegalArgumentException {
return nativeLockCanvas (dirty);
}
private native Canvas nativeLockCanvas (Rect dirty);
[android_view_Surface.cpp]
static jobject nativeLockCanvas (JNIEnv* env, jobject clazz, jobject dirtyRect)
{
sp<Surface> surface(getSurface(env, surfaceObj));
if (!Surface::isValid(surface)) {
doThrowIAE(env);
return NULL;
}
//1. 取得Dirty区域的大小.
Region dirtyRegion;
if (dirtyRectObj) {
Rect dirty;
dirty.left = env->GetIntField(dirtyRectObj, gRectClassInfo.left);
dirty.top = env->GetIntField(dirtyRectObj, gRectClassInfo.top);
dirty.right = env->GetIntField(dirtyRectObj, gRectClassInfo.right);
dirty.bottom = env->GetIntField(dirtyRectObj, gRectClassInfo.bottom);
if (!dirty.isEmpty()) {
dirtyRegion.set(dirty);
}
} else {
dirtyRegion.set(Rect(0x3FFF, 0x3FFF));
}
//2. 利用获得的Dirty区域利用Surface对象的lock函数来设置
//SurfaceInfo.
Surface::SurfaceInfo info;
status_t err = surface->lock(&info, &dirtyRegion);
//3. 从Java layer取得SkCanvas object.
// mCanvas在Surface建构之前就已经存在了,请参考程序代码 Surface.java
jobject canvas = env->GetObjectField(clazz, so.canvas);
//...
SkCanvas* nativeCanvas = (SkCanvas*)env->GetIntField(canvas,
no.native_canvas);
//4. 利用得到的SkCanvas来开始设定绘制区域.从Android 4.1开始绘制的
//类型有分SkBitmap内存管理跟 SkRegion内存管理.
//利用SurfaceInfo配置一块 2d skia的SkBitmap内存管理
SkBitmap bitmap;
ssize_t bpr = info.s * bytesPerPixel(info.format);
bitmap.setConfig(convertPixelFormat(info.format), info.w, info.h, bpr);
if (info.format == PIXEL_FORMAT_RGBX_8888) {
bitmap.setIsOpaque(true);
}
if (info.w > 0 && info.h > 0) {
//设定需要管理surface的buffer
bitmap.setPixels(info.bits);
} else {
// be safe with an empty bitmap.
bitmap.setPixels(NULL);
}
//SkCanvas设定此bitmap内存管理, 以便可以用这个内存管理在
//surface的buffer上作画.
nativeCanvas->setBitmapDevice(bitmap);
//配置一块 SkRegion内存管理
if (dirtyRegion.isRect()) { // very common case
const Rect b(dirtyRegion.getBounds());
clipReg.setRect(b.left, b.top, b.right, b.bottom);
} else {
size_t count;
Rect const* r = dirtyRegion.getArray(&count);
while (count) {
clipReg.op(r->left, r->top, r->right, r->bottom,
SkRegion::kUnion_Op);
r++, count--;
}
}
nativeCanvas->clipRegion(clipReg);
//5. 储存SkCanvas在内存管理上的配置.
int saveCount = nativeCanvas->save();
//6. 利用JNI的函数将一些需要的值来设定Java对象的属性.
return canvas;
}
[Surface.cpp]
status_t Surface::lock(SurfaceInfo* other, Region* inOutDirtyRegion) {
//...
//因为Surface类别衍生自 SurfaceTextureClient类别, 要呼叫父类别的
//函数需要父类别名子加上范围运算符.
status_t err = SurfaceTextureClient::lock(&outBuffer, inOutDirtyBounds);
//...
return err;
}
[SurfaceTextureClient.cpp]
status_t SurfaceTextureClient::lock(
ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds)
{
//0. already locked, retrun
if (!mConnectedToCpu) {
//
int err = SurfaceTextureClient::connect(NATIVE_WINDOW_API_CPU);
if (err) {
return err;
}
// we're intending to do software rendering from this point
setUsage(GRALLOC_USAGE_SW_READ_OFTEN |
GRALLOC_USAGE_SW_WRITE_OFTEN);
}
ANativeWindowBuffer* out;
//检查目前在queue中的buffer使用状态.并取出未使用的buffer index.
int fenceFd = -1;
status_t err = dequeueBuffer(&out, &fenceFd);
// 1. 宣告一个GraphicBuffer型态指针变量指向(ANativeWindowBuffer)out
//内存.
sp<GraphicBuffer> backBuffer(GraphicBuffer::getSelf(out));
//2. 依据backBuffer来设定需要更新的区域边界.
const Rect bounds(backBuffer->width, backBuffer->height);
Region newDirtyRegion;
if (inOutDirtyBounds) {
newDirtyRegion.set(static_cast<Rect const&>(*inOutDirtyBounds));
newDirtyRegion.andSelf(bounds);
} else {
newDirtyRegion.set(bounds);
}
//3. 检查是否有frontBuffer可以copy,以便显示到画面.
// mPostedBuffer跟之后要分析的 unlockCanvasAndPost处理有关.
const sp<GraphicBuffer>& frontBuffer(mPostedBuffer);
const bool canCopyBack = (frontBuffer != 0 &&
backBuffer->width == frontBuffer->width &&
backBuffer->height == frontBuffer->height &&
backBuffer->format == frontBuffer->format);
if (canCopyBack) {
// copy the area that is invalid and not repainted this round
const Region copyback(mDirtyRegion.subtract(newDirtyRegion));
if (!copyback.isEmpty())
//4. 避免整块memory做更新,因此只要藉由这方法来更新
//该更新的部分.
copyBlt(backBuffer, frontBuffer, copyback);
} else {
// if we can't copy-back anything, modify the user's dirty
// region to make sure they redraw the whole buffer
newDirtyRegion.set(bounds);
mDirtyRegion.clear();
Mutex::Autolock lock(mMutex);
for (size_t i=0 ; i<NUM_BUFFER_SLOTS ; i++) {
mSlots[i].dirtyRegion.clear();
}
}
// ...
void* vaddr;
//5. 依照newDirtyRegion的边界在backBuffer上lock一块内存并传回
//起始地址vaddr给jni中所宣告出来的SkBitmap使用.
status_t res = backBuffer->lock(
GRALLOC_USAGE_SW_READ_OFTEN |
GRALLOC_USAGE_SW_WRITE_OFTEN,
newDirtyRegion.bounds(), &vaddr);
//...
mLockedBuffer = backBuffer;
if (res != 0) {
err = INVALID_OPERATION;
} else {
mLockedBuffer = backBuffer;
outBuffer->width = backBuffer->width;
outBuffer->height = backBuffer->height;
outBuffer->stride = backBuffer->stride;
outBuffer->format = backBuffer->format;
outBuffer->bits = vaddr;
}
return err;
}
在分析lockCanvas中有个
dequeueBuffer的动作没有在这里分析,有兴趣再另起一个topic来分析.接下来继续分析unlockCanvasAndPost.
[Surface.java]
public void unlockCanvasAndPost(Canvas canvas) {
nativeUnlockCanvasAndPost(canvas);
}
private native void nativeUnlockCanvasAndPost(Canvas canvas);
[android_view_Surface.cpp]
static void nativeUnlockCanvasAndPost(JNIEnv* env, jobject surfaceObj, jobject canvasObj) {
jobject ownCanvasObj = env->GetObjectField(surfaceObj,
gSurfaceClassInfo.mCanvas);
if (!env->IsSameObject(ownCanvasObj, canvasObj)) {
doThrowIAE(env);
return;
}
const sp<Surface>& surface(getSurface(env, clazz));
if (!Surface::isValid(surface)) {
return;
}
SkCanvas* nativeCanvas = reinterpret_cast<SkCanvas*>(
env->GetIntField(canvasObj, gCanvasClassInfo.mNativeCanvas));
int saveCount = env->GetIntField(surfaceObj,
gSurfaceClassInfo.mCanvasSaveCount);
nativeCanvas->restoreToCount(saveCount);
nativeCanvas->setBitmapDevice(SkBitmap());
env->SetIntField(surfaceObj, gSurfaceClassInfo.mCanvasSaveCount, 0);
status_t err = surface->unlockAndPost();
if (err < 0) {
doThrowIAE(env);
}
}
[Surface.cpp]
status_t Surface::unlockAndPost() {
//因为Surface类别衍生自 SurfaceTextureClient类别, 要呼叫父类别的
//函数需要父类别名子加上范围运算符.
return SurfaceTextureClient::unlockAndPost();
}
[SurfaceTextureClient.cpp]
status_t SurfaceTextureClient::unlockAndPost()
{
//...
//0. 将使用完的Buffer做unlock的动作.
status_t err = mLockedBuffer->unlock();
//...
//1. 将unlock的buffer index送进queue中.
err = queueBuffer(mLockedBuffer.get());
//...
//2. 将mLockedBuffer指针对象传给mPostedBuffer指针对象做为下一次
// lockCanvas的依据.
mPostedBuffer = mLockedBuffer;
mLockedBuffer = 0;
}
关于View的Draw流程就不在这一次的分析中, 因为Surface中的Canvas和Bitmap对View的Draw流程来说只是个工具. 总结如下:
1. 在App开始要布局layout view都会由setContentView来设置整体画面.
这时的角色有PhoneWindow, WindowManagerImpl, DecoreView
其相互动作如下:
a. getWindow 得到一个 mWindow, 这个 mWindow 就是一个
PhoneWindow 物件.
b. 利用 PhoneWindow 对象设为 WindowManagerImpl的角色.
c. PhoneWindow 物件设置一个 DecoreView 的子 view.
2. 当App从Create状态转到Resume状态时, 这时就会开始绘制画面.
角色: DecoreView, WindowManagerImpl, ViewRootImpl,WindowManagerService,
SurfaceSession, WindowState, Surface, Canvas
i. ViewRootImpl利用Binder机制将WindowManagerService 和 DecoreView建立一个session.
ii. ViewRootImpl经由session请求WindowManagerService来增加一个WindowState,并作记录.
iii. WindowManagerService在作windowstate时, 会建构一个SurfaceComposerClient物件.
iv. 利用SurfaceComposerClient对象产生SurfaceControl对象.
v. 利用Canvas设置两个Buffer, 分别为Front和Back.
vi. 利用Surface对象的lockCanvas, unlockCanvasAndPost函数来处理绘制画面的流程.