WMS相关学习-Surface(7)

前言

前面几章主要阐述了窗口相关数据结构的创建,窗口的大小的计算,布局等等问题;本章主要学习与Surface相关的一些代码,Surface与窗口的显示息息相关

Surface创建相关逻辑

Android Surface的创建涉及三个进程
1.App 进程
Surface本质上是一个Native Window, 并且保存着需要在屏幕上显示的数据(buffer), 它通常包含 triple-buffers 以防止Jank。
那么谁要创建Surface呢? 当然是App了,App需要将自己的内容显示在屏幕上,所以App负责发起Surface创建请求,创建好Surface后, 就可以直接可以在canvas上画图等,最终都会保存到Surface里的buffer里,最后由SurfaceFlinger合成并显示。
2.System_Server进程
主要是其中的WindowManagerService, 负责接收APP请求,向SurfaceFlinger发起具体的请求创建Surface, 且WMS需要创建Surface的辅助管理类,如SurfaceControl(与Window一一对应)。
为什么需要与system进程打交道呢?App直接通知SurfaceFlinger创建Surface不就行了?为什么还需要通过system进程呢?个人猜想可能是统一由WMS管理,以及当前系统中的窗口的Z -order计算, 减轻SurfaceFlinger的负担。
3.SurfaceFlinger
为App进程创建具体的Surface, 在SurfaceFlinger里对应成Layer, 然后负责管理、合成显示。

前面说到会在WMS的relayoutWindow调用createSurfaceControl

system_server端的SurfaceControl(java和native)

WindowManagerService#createSurfaceControl

创建windowState对应的SurfaceControl

private int createSurfaceControl(Surface outSurface, int result, WindowState win,
        WindowStateAnimator winAnimator) {
    if (!win.mHasSurface) {
        result |= RELAYOUT_RES_SURFACE_CHANGED;
    }

    WindowSurfaceController surfaceController;
    try {
        Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "createSurfaceControl");
        //SurfaceControl: 用于创建、获取、设置Surface   
        surfaceController = winAnimator.createSurfaceLocked(win.mAttrs.type, win.mOwnerUid);
    } finally {
        Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
    }
    if (surfaceController != null) {
       //进行copy
        surfaceController.getSurface(outSurface); //outSurface赋值为win.mWinAnimator.mSurfaceController.mSurfaceControl
        if (SHOW_TRANSACTIONS) Slog.i(TAG_WM, "  OUT SURFACE " + outSurface + ": copied");
    } else {
        // For some reason there isn't a surface.  Clear the
        // caller's object so they see the same state.
        Slog.w(TAG_WM, "Failed to create surface control for " + win);
        outSurface.release();
    }
    return result;
}

WindowStateAnimator#createSurfaceLocked

创建WindowSurfaceController

WindowSurfaceController createSurfaceLocked(int windowType, int ownerUid) {
    final WindowState w = mWin;

    if (mSurfaceController != null) {
        return mSurfaceController;
    }
    mChildrenDetached = false;

    if ((mWin.mAttrs.privateFlags & PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY) != 0 ) {
        windowType = SurfaceControl.WINDOW_TYPE_DONT_SCREENSHOT;
    }

    w.setHasSurface(false);

    if (DEBUG_ANIM || DEBUG_ORIENTATION) Slog.i(TAG,
            "createSurface " + this + ": mDrawState=DRAW_PENDING");

    resetDrawState();

    mService.makeWindowFreezingScreenIfNeededLocked(w);

    int flags = SurfaceControl.HIDDEN;
    final WindowManager.LayoutParams attrs = w.mAttrs;

    if (mService.isSecureLocked(w)) {
        flags |= SurfaceControl.SECURE;
    }

    mTmpSize.set(0, 0, 0, 0);
    calculateSurfaceBounds(w, attrs);
    final int width = mTmpSize.width();
    final int height = mTmpSize.height();

    if (DEBUG_VISIBILITY) {
        Slog.v(TAG, "Creating surface in session "
                + mSession.mSurfaceSession + " window " + this
                + " w=" + width + " h=" + height
                + " x=" + mTmpSize.left + " y=" + mTmpSize.top
                + " format=" + attrs.format + " flags=" + flags);
    }

    // We may abort, so initialize to defaults.
    mLastClipRect.set(0, 0, 0, 0);

    // Set up surface control with initial size.
    try {

        final boolean isHwAccelerated = (attrs.flags & FLAG_HARDWARE_ACCELERATED) != 0;
        final int format = isHwAccelerated ? PixelFormat.TRANSLUCENT : attrs.format;
        if (!PixelFormat.formatHasAlpha(attrs.format)
                // Don't make surface with surfaceInsets opaque as they display a
                // translucent shadow.
                && attrs.surfaceInsets.left == 0
                && attrs.surfaceInsets.top == 0
                && attrs.surfaceInsets.right == 0
                && attrs.surfaceInsets.bottom == 0
                // Don't make surface opaque when resizing to reduce the amount of
                // artifacts shown in areas the app isn't drawing content to.
                && !w.isDragResizing()) {
            flags |= SurfaceControl.OPAQUE;
        }

        mSurfaceController = new WindowSurfaceController(mSession.mSurfaceSession,
                attrs.getTitle().toString(), width, height, format, flags, this,
                windowType, ownerUid); //调用WindowSurfaceController构造函数,为mSurfaceControl赋值

        setOffsetPositionForStackResize(false);
        mSurfaceFormat = format;

        w.setHasSurface(true); //将WindowState的mHasSurface置为true

        if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
            Slog.i(TAG, "  CREATE SURFACE "
                    + mSurfaceController + " IN SESSION "
                    + mSession.mSurfaceSession
                    + ": pid=" + mSession.mPid + " format="
                    + attrs.format + " flags=0x"
                    + Integer.toHexString(flags)
                    + " / " + this);
        }
    } catch (OutOfResourcesException e) {
        Slog.w(TAG, "OutOfResourcesException creating surface");
        mService.mRoot.reclaimSomeSurfaceMemory(this, "create", true);
        mDrawState = NO_SURFACE;
        return null;
    } catch (Exception e) {
        Slog.e(TAG, "Exception creating surface (parent dead?)", e);
        mDrawState = NO_SURFACE;
        return null;
    }

    if (WindowManagerService.localLOGV) Slog.v(TAG, "Got surface: " + mSurfaceController
            + ", set left=" + w.mFrame.left + " top=" + w.mFrame.top
            + ", animLayer=" + mAnimLayer);

    if (SHOW_LIGHT_TRANSACTIONS) {
        Slog.i(TAG, ">>> OPEN TRANSACTION createSurfaceLocked");
        WindowManagerService.logSurface(w, "CREATE pos=("
                + w.mFrame.left + "," + w.mFrame.top + ") ("
                + width + "x" + height + "), layer=" + mAnimLayer + " HIDE", false);
    }

    mLastHidden = true;

    if (WindowManagerService.localLOGV) Slog.v(TAG, "Created surface " + this);
    return mSurfaceController; //返回WindowSurfaceController对象 (win.mWinAnimator.mSurfaceController)
}
WindowSurfaceController构造函数
public WindowSurfaceController(SurfaceSession s, String name, int w, int h, int format,
        int flags, WindowStateAnimator animator, int windowType, int ownerUid) {
    mAnimator = animator;

    mSurfaceW = w;
    mSurfaceH = h;

    title = name;

    mService = animator.mService;
    final WindowState win = animator.mWin;
    mWindowType = windowType;
    mWindowSession = win.mSession;

    Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "new SurfaceControl");
    final SurfaceControl.Builder b = win.makeSurface()
            .setParent(win.getSurfaceControl())
            .setName(name)
            .setSize(w, h)
            .setFormat(format)
            .setFlags(flags)
            .setMetadata(windowType, ownerUid);
    mSurfaceControl = b.build();
    Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}

创建java层的SurfaceControl,此时进程相应的SurfaceSession已经创建完毕

SurfaceControl$Builder#build
/**
 * Builder class for {@link SurfaceControl} objects.
 */
public static class Builder {
    private SurfaceSession mSession;
    private int mFlags = HIDDEN;
    private int mWidth;
    private int mHeight;
    private int mFormat = PixelFormat.OPAQUE;
    private String mName;
    private SurfaceControl mParent;
    private int mWindowType = -1;
    private int mOwnerUid = -1;

    /**
     * Begin building a SurfaceControl with a given {@link SurfaceSession}.
     *
     * @param session The {@link SurfaceSession} with which to eventually construct the surface.
     */
    public Builder(SurfaceSession session) {
        mSession = session;
    }

    /**
     * Construct a new {@link SurfaceControl} with the set parameters.
     */
    public SurfaceControl build() {
        if (mWidth <= 0 || mHeight <= 0) {
            throw new IllegalArgumentException(
                    "width and height must be set");
        }
        return new SurfaceControl(mSession, mName, mWidth, mHeight, mFormat,
                mFlags, mParent, mWindowType, mOwnerUid); 
        //java层创建SurfaceControl
    }

SurfaceControl#SurfaceControl

/**
 * Create a surface with a name.
 * <p>
 * The surface creation flags specify what kind of surface to create and
 * certain options such as whether the surface can be assumed to be opaque
 * and whether it should be initially hidden.  Surfaces should always be
 * created with the {@link #HIDDEN} flag set to ensure that they are not
 * made visible prematurely before all of the surface's properties have been
 * configured.
 * <p>
 * Good practice is to first create the surface with the {@link #HIDDEN} flag
 * specified, open a transaction, set the surface layer, layer stack, alpha,
 * and position, call {@link #show} if appropriate, and close the transaction.
 *
 * @param session The surface session, must not be null.
 * @param name The surface name, must not be null.
 * @param w The surface initial width.
 * @param h The surface initial height.
 * @param flags The surface creation flags.  Should always include {@link #HIDDEN}
 * in the creation flags.
 * @param windowType The type of the window as specified in WindowManager.java.
 * @param ownerUid A unique per-app ID.
 *
 * @throws throws OutOfResourcesException If the SurfaceControl cannot be created.
 */
private SurfaceControl(SurfaceSession session, String name, int w, int h, int format, int flags,
        SurfaceControl parent, int windowType, int ownerUid)
                throws OutOfResourcesException, IllegalArgumentException {
    if (session == null) {
        throw new IllegalArgumentException("session must not be null");
    }
    if (name == null) {
        throw new IllegalArgumentException("name must not be null");
    }

    if ((flags & SurfaceControl.HIDDEN) == 0) {
        Log.w(TAG, "Surfaces should always be created with the HIDDEN flag set "
                + "to ensure that they are not made visible prematurely before "
                + "all of the surface's properties have been configured.  "
                + "Set the other properties and make the surface visible within "
                + "a transaction.  New surface name: " + name,
                new Throwable());
    }

    mName = name;
    mWidth = w;
    mHeight = h;
    mNativeObject = nativeCreate(session, name, w, h, format, flags,
        parent != null ? parent.mNativeObject : 0, windowType, ownerUid); //mNativeObject 指向native层的SurfaceControl
    if (mNativeObject == 0) {
        throw new OutOfResourcesException(
                "Couldn't allocate SurfaceControl native object");
    }

    mCloseGuard.open("release");
}

进入JNI,创建native层的SurfaceControl

android_view_SurfaceControl#nativeCreate

SurfaceControl中的client为SurfaceComposerClient

static jlong nativeCreate(JNIEnv* env, jclass clazz, jobject sessionObj,
        jstring nameStr, jint w, jint h, jint format, jint flags, jlong parentObject,
        jint windowType, jint ownerUid) {
    ScopedUtfChars name(env, nameStr);
    sp<SurfaceComposerClient> client(android_view_SurfaceSession_getClient(env, sessionObj));
    SurfaceControl *parent = reinterpret_cast<SurfaceControl*>(parentObject);
    sp<SurfaceControl> surface;
    status_t err = client->createSurfaceChecked(
            String8(name.c_str()), w, h, format, &surface, flags, parent, windowType, ownerUid); //此时创建好了SurfaceFlinger中的surface以及WMS中对应的SurfaceControl
    if (err == NAME_NOT_FOUND) {
        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
        return 0;
    } else if (err != NO_ERROR) {
        jniThrowException(env, OutOfResourcesException, NULL);
        return 0;
    }

    surface->incStrong((void *)nativeCreate);
    return reinterpret_cast<jlong>(surface.get());
}

返回的是native的SurfaceControl的指针;其创建时通过调用client(SurfaceComposerClient)的createSurfaceChecked进行创建的;

SurfaceComposerClient的创建流程

android_view_SurfaceSession_getClient 这里关系到SurfaceSession类;首先在WindowManagerService#addWindow中会调用win.attach();则其在相应窗口走到performTraversals的relayoutWindow之前,说明先创建SurfaceSession(与进程对应),再创建Window对应的SurfaceControl

WindowState#attach
void attach() {
    if (localLOGV) Slog.v(TAG, "Attaching " + this + " token=" + mToken);
    mSession.windowAddedLocked(mAttrs.packageName);
}
Session#windowAddedLocked
void windowAddedLocked(String packageName) {
    mPackageName = packageName;
    mRelayoutTag = "relayoutWindow: " + mPackageName;
    if (mSurfaceSession == null) {
        if (WindowManagerService.localLOGV) Slog.v(
            TAG_WM, "First window added to " + this + ", creating SurfaceSession");
        mSurfaceSession = new SurfaceSession();
        if (SHOW_TRANSACTIONS) Slog.i(
                TAG_WM, "  NEW SURFACE SESSION " + mSurfaceSession);
        mService.mSessions.add(this);
        if (mLastReportedAnimatorScale != mService.getCurrentAnimatorScale()) {
            mService.dispatchNewAnimatorScaleLocked(this);
        }
    }
    mNumWindow++;
}

创建SurfaceSession

/** Create a new connection with the surface flinger. */
public SurfaceSession() {
    mNativeClient = nativeCreate(); //创建SurfaceComposerClient对象,并将其JNI对象地址保存到mNativeClient中
}

java层的SurfaceSession;保存了jni层创建的SurfaceComposerClient的地址

android_view_SurfaceSeesion#nativeCreate
static jlong nativeCreate(JNIEnv* env, jclass clazz) {
    SurfaceComposerClient* client = new SurfaceComposerClient(); //创建SurfaceComposerClient(与进程对应)
    client->incStrong((void*)nativeCreate);
    return reinterpret_cast<jlong>(client);
}
SurfaceComposerClient的构造函数
SurfaceComposerClient::SurfaceComposerClient()
    : mStatus(NO_INIT)
{
}

所以前面android_view_SurfaceControl中的client就是sp<SurfaceComposerClient>

创建native SurfaceControl

SurfaceComposerClient::createSurfaceChecked

status_t SurfaceComposerClient::createSurfaceChecked(
        const String8& name,
        uint32_t w,
        uint32_t h,
        PixelFormat format,
        sp<SurfaceControl>* outSurface,
        uint32_t flags,
        SurfaceControl* parent,
        int32_t windowType,
        int32_t ownerUid)
{
    sp<SurfaceControl> sur;
    status_t err = mStatus;

    if (mStatus == NO_ERROR) {
        sp<IBinder> handle;
        sp<IBinder> parentHandle;
        sp<IGraphicBufferProducer> gbp;

        if (parent != nullptr) {
            parentHandle = parent->getHandle();
        }
        err = mClient->createSurface(name, w, h, format, flags, parentHandle,
                windowType, ownerUid, &handle, &gbp); //可见这里是调用SurfaceFlinger进程中的Client的createSurface,创建Surface;并返回SurfaceFlinger中的Handle以及IGraphicsBufferProducer的代理
        ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err));
        if (err == NO_ERROR) {
            *outSurface = new SurfaceControl(this, handle, gbp, true /* owned */);  //native层创建SurfaceControl
            //当SurfaceFlinger中创建好Surface后,在WMS的JNI层创建一个SurfaceControl, SurfaceControl顾名思义就是控制、操作Surface的类
        }
    }
    return err;
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 转载请标注来处: http://www.jianshu.com/p/64e5c866b4ae 一、 OverVi...
    wbo4958阅读 23,008评论 4 48
  • 本篇文章是基于谷歌有关Graphic的一篇概览文章的翻译:http://source.android.com/de...
    lee_3do阅读 7,209评论 2 21
  • 1:InputChannel提供函数创建底层的Pipe对象 2: 1)客户端需要新建窗口 2)new ViewRo...
    自由人是工程师阅读 5,403评论 0 18
  • 前言 在android应用程序四大组件中,Activity负责界面的展示, 同时android系统是基于linux...
    Jimmy2012阅读 5,048评论 1 24
  • 1.上周我们进行了2018年的中考,完成了本学期最重要的考试。通过考试他们将走向更高一级学校学习。 2.常规管理 ...
    lucks368阅读 139评论 0 0