Android学习之Surface一,application与surface的关系

时间:2023-02-02 08:05:40

读书笔记,作为备忘。书是"深入理解android"

好开始。

Surface最早出现在ViewRoot中,这时的mSurface只是一块简单的画布,没和底层接触,还不能在屏幕上进行UI绘制。

private final Surface mSurface = new Surface();

Activity的显示经过ViewRoot的setView(),requestLayout(),scheduleTraversals(),走到performTraversals()

private void performTraversals(){
...
try{
...
//跳转到WmS的relayout()
relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
...
}
performDraw();//实际draw(fullRedrawNeeded);
}
relayoutWindows(...)主要用于将上面的mSurface与底层Surface对应起来,主要注意参数mSurface,

--ViewRoot.java

private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,
            boolean insetsPending) throws RemoteException {
//远程调用WMS
nt relayoutResult = mWindowSession.relayout(
                mWindow, mSeq, params,
                (int) (mView.getMeasuredWidth() * appScale + 0.5f),
                (int) (mView.getMeasuredHeight() * appScale + 0.5f),
                viewVisibility, insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0,
                mWinFrame, mPendingContentInsets, mPendingVisibleInsets,
                mPendingConfiguration, mSurface);
}

--WindowsManagerService.java::Session

public int relayout(IWindow window, int seq, WindowManager.LayoutParams attrs,
            int requestedWidth, int requestedHeight, int viewFlags,
            int flags, Rect outFrame, Rect outContentInsets,
            Rect outVisibleInsets, Configuration outConfig, Surface outSurface) {
        int res = mService.relayoutWindow(this, window, seq, attrs,
                requestedWidth, requestedHeight, viewFlags, flags,
                outFrame, outContentInsets, outVisibleInsets,
                outConfig, outSurface);
    }

--WindowsManagerService.java

public int relayoutWindow(Session session, IWindow client, int seq,
            WindowManager.LayoutParams attrs, int requestedWidth,
            int requestedHeight, int viewVisibility, int flags,
            Rect outFrame, Rect outContentInsets,
            Rect outVisibleInsets, Configuration outConfig, Surface outSurface) {

Surface surface = winAnimator.createSurfaceLocked();//通过SurfaceSession创建surface
outSurface.copyFrom(surface);// 这里将surface返回给ViewRoot的mSurface
}
Surface createSurfaceLocked() {
mSurface = new Surface(
                        mSession.mSurfaceSession,
                        attrs.getTitle().toString(),
                        w, h, format, flags);
}
--Surface.java

public Surface(SurfaceSession session,
            String name, int w, int h, int format, int flags)
            throws OutOfResourcesException {
...
        nativeCreate(session, name, w, h, format, flags);

    }

--andoid_view_Surface.cpp

static void nativeCreate(JNIEnv* env, jobject surfaceObj, jobject sessionObj,
        jstring nameStr, jint w, jint h, jint format, jint flags) {
    ScopedUtfChars name(env, nameStr);
    sp<SurfaceComposerClient> client(android_view_SurfaceSession_getClient(env, sessionObj));

    sp<SurfaceControl> surface = client->createSurface(
            String8(name.c_str()), w, h, format, flags);
    if (surface == NULL) {
        jniThrowException(env, OutOfResourcesException, NULL);
        return;
    }

    setSurfaceControl(env, surfaceObj, surface);
}

这时的mSurface已经是Native的Surface,可以对屏幕进行操作,真正的可以在屏幕上绘制UI。关键是SurfaceSession的加入。

--SurfaceSesson.java

public SurfaceSession() {
        mNativeClient = nativeCreate();
    }

--andoid_view_SurfaceSession.cpp

static jint nativeCreate(JNIEnv* env, jclass clazz) {
    SurfaceComposerClient* client = new SurfaceComposerClient();
    client->incStrong(clazz);
    return reinterpret_cast<jint>(client);
}

SurfaceSesson在native层创建了SurfaceComposerClient对象client。client创建了native的SurfaceControl类型的surface,copyFrom的过程中从SurfaceControl信息中构造出Surface类型放入mSurface ,完成mSurface与底层相Surface对应。

draw(fullRedrawNeed) 中的drawSoftware(surface, attachInfo, yoff, scalingRequired, dirty)绘制UI。

private boolean drawSoftware(Surface surface, AttachInfo attachInfo, int yoff,
            boolean scalingRequired, Rect dirty) {
...
canvas = mSurface.lockCanvas(dirty);
...
mView.draw(canvas);
...
surface.unlockCanvasAndPost(canvas);
}