AOSP-Surface

基础概念梳理

个人理解

在android中编写的view,最终需要通过OpenGl Es/Skia(Q以后使用Skia)向物理屏幕输出,最终显示我们要显示的画面。

在这个过程中,android 需要提供一块画布,让我们可以编写自己要显示的东西,这里面就涉及到SF(SurfaceFlinger) 和Surface,FrameBuffer等。 FrameBuffer 则是帧缓存驱动,就是系统特地为显示保留的一块内存, 输出需要显示的内容就往这里写,屏幕需要显示的时候,也是从这里取,一般数量为2,也就是双缓冲,也有三缓冲。

Surface到底是什么? 对应内存里的一块区域,由SF分配,app会从SF那获取一块GraphicBuffer,通过OpenGL/Skia 将图形绘制到GraphicBuffer上,SF会把各个应用的GraphicBuffer进行合成,最终通过SF 输出到屏幕上。 简单说就是SF的给的一块内存。

正常一个页面,顶部状态栏是一个buffer,底部导航栏是一个,中间的页面是一个,最终他们会被合成为一帧画面。

基础类和方法

ViewRoot中的Surface 创建过程 涉及如下几个类和类里参数

ViewRootImp.java

属性
java 复制代码
//空的构造 其实只是个占位后期需要copyFrom才能真正赋值 准确说是个壳子
public final Surface mSurface = new Surface();
//空构造 无用 后期也是赋值过来 
private final SurfaceControl mSurfaceControl = new SurfaceControl()
// mWindowSession 实际是Session的一个aidl的代理类  在当前类是唯一的 整个app有且只有一个
final IWindowSession mWindowSession;
//构造函数会调用到nativeCreate 会调用android_view_SurfaceSession.cpp里面的nativeCreate 是SF在C端的引用
private final SurfaceSession mSurfaceSession = new SurfaceSession();
​
final W mWindow;
​
注意点
  • 为什么app里只有一个Session

    java 复制代码
    //构造函数获取Session
    public ViewRootImpl(Context context, Display display) {
            this(context, display, WindowManagerGlobal.getWindowSession(),
                    false /* useSfChoreographer */);
        }
        
    ​
    WindowManagerGlobal.java -->getWindowSession()
      //单例模式 跨进程 从WindowManagerService 获取 WindowManagerService 是继承实现了 IWindowManager.Stub
      public static IWindowSession getWindowSession() {
            synchronized (WindowManagerGlobal.class) {
                if (sWindowSession == null) {
                    try {
                     InputMethodManager.ensureDefaultInstanceForDefaultDisplayIfNecessary();
                        IWindowManager windowManager = getWindowManagerService();
                        sWindowSession = windowManager.openSession(
                                new IWindowSessionCallback.Stub() {
                                    @Override
                                    public void onAnimatorScaleChanged(float scale) {
                                        ValueAnimator.setDurationScale(scale);
                                    }
                                });
                    } catch (RemoteException e) {
                        throw e.rethrowFromSystemServer();
                    }
                }
                return sWindowSession;
            }
        }
        
方法

入口

setView 会调用如下两个方法

scss 复制代码
requestLayout();->scheduleTraversals();->doTraversal()->  performTraversals()->
relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
-->
  //这里调用了Session.relayout 传递参数给Session
  //注意这里的params 和宽高都传递过去了 因为在SF那边图层 需要宽高和format 类型 比如argb888之类的
  //实际调用是wms的relayoutWindow
  int relayoutResult = mWindowSession.relayout(mWindow, params,
                (int) (mView.getMeasuredWidth() * appScale + 0.5f),
                (int) (mView.getMeasuredHeight() * appScale + 0.5f), viewVisibility,
                insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0,           frameNumber,
                mTmpFrames, mPendingMergedConfiguration, mSurfaceControl, mTempInsets,
                mTempControls, mSurfaceSize);
​
    //这里是个重点 将mSurfaceControl里面的mNativeObject copy 过来 所以其实surface就是空壳子
    mSurface.copyFrom(mSurfaceControl);
less 复制代码
//调用Session的addToDisplayAsUser  实际是调用了wms的addWindow
res = mWindowSession.addToDisplayAsUser(mWindow, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(), userId, mInsetsController.getRequestedVisibility(), inputChannel, mTempInsets,
                            mTempControls);

Surface.java

copyFrom()
ini 复制代码
    @UnsupportedAppUsage
    public void copyFrom(SurfaceControl other) {
        if (other == null) {
            throw new IllegalArgumentException("other must not be null");
        }
​
        long surfaceControlPtr = other.mNativeObject;
        if (surfaceControlPtr == 0) {
            throw new NullPointerException(
                    "null SurfaceControl native object. Are you using a released SurfaceControl?");
        }
        long newNativeObject = nativeGetFromSurfaceControl(mNativeObject, surfaceControlPtr);
        updateNativeObject(newNativeObject);
    }
​

Session.java

relayout
java 复制代码
@Override
public int relayout(IWindow window, WindowManager.LayoutParams attrs,
        int requestedWidth, int requestedHeight, int viewFlags, int flags, long frameNumber,
        ClientWindowFrames outFrames, MergedConfiguration mergedConfiguration,
        SurfaceControl outSurfaceControl, InsetsState outInsetsState,
        InsetsSourceControl[] outActiveControls, Point outSurfaceSize) {
    int res = mService.relayoutWindow(this, window, attrs,
            requestedWidth, requestedHeight, viewFlags, flags, frameNumber,
            outFrames, mergedConfiguration, outSurfaceControl, outInsetsState,
            outActiveControls, outSurfaceSize);
​
    return res;
}
addToDisplayAsUser
arduino 复制代码
public int addToDisplayAsUser(IWindow window, WindowManager.LayoutParams attrs,
        int viewVisibility, int displayId, int userId, InsetsState requestedVisibility,
        InputChannel outInputChannel, InsetsState outInsetsState,
        InsetsSourceControl[] outActiveControls) {
  //wms 添加window
    return mService.addWindow(this, window, attrs, viewVisibility, displayId, userId,
            requestedVisibility, outInputChannel, outInsetsState, outActiveControls);
}
windowAddedLocked
csharp 复制代码
void windowAddedLocked() {
    if (mPackageName == null) {
        final WindowProcessController wpc = mService.mAtmService.mProcessMap.getProcess(mPid);
        if (wpc != null) {
            mPackageName = wpc.mInfo.packageName;
            mRelayoutTag = "relayoutWindow: " + mPackageName;
        } else {
            Slog.e(TAG_WM, "Unknown process pid=" + mPid);
        }
    }
    if (mSurfaceSession == null) {
        if (DEBUG) {
            Slog.v(TAG_WM, "First window added to " + this + ", creating SurfaceSession");
        }
      //创建新 的SurfaceSession  在他的构造函数里会和native 通信
        mSurfaceSession = new SurfaceSession(); 
        ProtoLog.i(WM_SHOW_TRANSACTIONS, "  NEW SURFACE SESSION %s", mSurfaceSession);
      //wms里面的 mSessions 开始管理该Session
        mService.mSessions.add(this);
        if (mLastReportedAnimatorScale != mService.getCurrentAnimatorScale()) {
            mService.dispatchNewAnimatorScaleLocked(this);
        }
    }
  // 窗口数量增加
    mNumWindow++;
}

WindowManagerService.java

addWindow()
ini 复制代码
//核心代码 创建WindowState 并调用 attach
final WindowState win = new WindowState(this, session, client, token, parentWindow,
        appOp[0], attrs, viewVisibility, session.mUid, userId,
        session.mCanAddInternalSystemWindow);...
 win.attach();
relayoutWindow
ini 复制代码
//申请宽高
if (viewVisibility != View.GONE) {  win.setRequestedSize(requestedWidth, requestedHeight);}
attrChanges = win.mAttrs.copyFrom(attrs);
//将viewRootimp 里面的 outSurfaceControl 传入方法开始创建
  result = createSurfaceControl(outSurfaceControl, result, win, winAnimator);
​
createSurfaceControl
ini 复制代码
//调用winAnimator 
surfaceController = winAnimator.createSurfaceLocked(win.mAttrs.type);
// copyFrom 赋值给viewRootImp里的SurfaceControl
  surfaceController.getSurfaceControl(outSurfaceControl);

WindowState.java

attach()
csharp 复制代码
void attach() {
    if (DEBUG) Slog.v(TAG, "Attaching " + this + " token=" + mToken);
    mSession.windowAddedLocked();
}

SurfaceSession.java

构造函数
scss 复制代码
public SurfaceSession() {
    mNativeClient = nativeCreate();
}

WindowStateAnimator.java

createSurfaceLocked
scss 复制代码
//如果不为null 则直接返回 
if (mSurfaceController != null) {
    return mSurfaceController;
}
//否则创建
  mSurfaceController = new WindowSurfaceController(attrs.getTitle().toString(), width,
                    height, format, flags, this, windowType);

WindowSurfaceController.java

构造函数(String name, int w, int h, int format,
arduino 复制代码
    int flags, WindowStateAnimator animator, int windowType)
scss 复制代码
//会调用到SurfaceControl里的build()     
final SurfaceControl.Builder b = win.makeSurface()
                .setParent(win.getSurfaceControl())
                .setName(name)
                .setBufferSize(w, h)
                .setFormat(format)
                .setFlags(flags)
                .setMetadata(METADATA_WINDOW_TYPE, windowType)
                .setMetadata(METADATA_OWNER_UID, mWindowSession.mUid)
                .setMetadata(METADATA_OWNER_PID, mWindowSession.mPid)
                .setCallsite("WindowSurfaceController");
​
        final boolean useBLAST = mService.mUseBLAST && ((win.getAttrs().privateFlags
                & WindowManager.LayoutParams.PRIVATE_FLAG_USE_BLAST) != 0);
​
        if (useBLAST) {
            b.setBLASTLayer();
        }
​
        mSurfaceControl = b.build();

SurfaceControl.java

mNativeObject

这里的mNativeObject 其实指向的就是SF给开辟的内存地址,后期会赋值给ViewRootImp里的surface

多构造参数方法
ini 复制代码
mNativeObject = nativeCreate(session, name, w, h, format, flags,
    parent != null ? parent.mNativeObject : 0, metaParcel);
build()
scss 复制代码
public SurfaceControl build() {
            if (mWidth < 0 || mHeight < 0) {
                throw new IllegalStateException(
                        "width and height must be positive or unset");
            }
            if ((mWidth > 0 || mHeight > 0) && (isEffectLayer() || isContainerLayer())) {
                throw new IllegalStateException(
                        "Only buffer layers can set a valid buffer size.");
            }
​
            if ((mFlags & FX_SURFACE_MASK) == FX_SURFACE_NORMAL) {
                setBLASTLayer();
            }
​
            return new SurfaceControl(
                    mSession, mName, mWidth, mHeight, mFormat, mFlags, mParent, mMetadata,
                    mLocalOwnerView, mCallsite);
        }
getSurfaceControl
javascript 复制代码
void getSurfaceControl(SurfaceControl outSurfaceControl) {
    outSurfaceControl.copyFrom(mSurfaceControl, "WindowSurfaceController.getSurfaceControl");
}

android_view_surfaceControl.cpp

nativeCreate()
scss 复制代码
static jlong nativeCreate(JNIEnv* env, jclass clazz, jobject sessionObj,
        jstring nameStr, jint w, jint h, jint format, jint flags, jlong parentObject,
        jobject metadataParcel) {
    ScopedUtfChars name(env, nameStr);
    sp<SurfaceComposerClient> client;
  //创建sf 在C端的代理
    if (sessionObj != NULL) {
      //从session拿 其实调用的是android_view_SurfaceSession.cpp里面的mNativeClient
      //然后从SurfaceSession 获取 mNativeClient  其实就是一个 SurfaceComposerClient
        client = android_view_SurfaceSession_getClient(env, sessionObj);
    } else {
      //获取默认的cliden 返回一个 SurfaceComposerClient
        client = SurfaceComposerClient::getDefault();
    }
    SurfaceControl *parent = reinterpret_cast<SurfaceControl*>(parentObject);
    sp<SurfaceControl> surface;
    LayerMetadata metadata;
    Parcel* parcel = parcelForJavaObject(env, metadataParcel);
    if (parcel && !parcel->objectsCount()) {
        status_t err = metadata.readFromParcel(parcel);
        if (err != NO_ERROR) {
          jniThrowException(env, "java/lang/IllegalArgumentException",
                            "Metadata parcel has wrong format");
        }
    }
​
    sp<IBinder> parentHandle;
    if (parent != nullptr) {
        parentHandle = parent->getHandle();
    }
​
  //sf 创建Surface
    status_t err = client->createSurfaceChecked(String8(name.c_str()), w, h, format, &surface,
                                                flags, parentHandle, std::move(metadata));
    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());
}

android_view_SurfaceSession.cpp

nativeCreate()
scss 复制代码
static jlong nativeCreate(JNIEnv* env, jclass clazz) {
    SurfaceComposerClient* client = new SurfaceComposerClient();
    client->incStrong((void*)nativeCreate);
    return reinterpret_cast<jlong>(client);
}
register_android_view_SurfaceSession
ini 复制代码
//其实从SurfaceSession.java去获取mNativeClient  赋值给 自己内部的mNativeClient
int register_android_view_SurfaceSession(JNIEnv* env) {
    int res = jniRegisterNativeMethods(env, "android/view/SurfaceSession",
            gMethods, NELEM(gMethods));
    LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register native methods.");
​
    jclass clazz = env->FindClass("android/view/SurfaceSession");
    gSurfaceSessionClassInfo.mNativeClient = env->GetFieldID(clazz, "mNativeClient", "J");
    return 0;
}

SurfaceComposerClient.cpp

createSurfaceChecked()
ini 复制代码
status_t SurfaceComposerClient::createSurfaceChecked(const String8& name, uint32_t w, uint32_t h,
                                                     PixelFormat format,
                                                     sp<SurfaceControl>* outSurface, uint32_t flags,
                                                     const sp<IBinder>& parentHandle,
                                                     LayerMetadata metadata,
                                                     uint32_t* outTransformHint) {
    sp<SurfaceControl> sur;
    status_t err = mStatus;
​
    if (mStatus == NO_ERROR) {
        sp<IBinder> handle;
        sp<IGraphicBufferProducer> gbp;
​
        uint32_t transformHint = 0;
        int32_t id = -1;
         //创建surface
        err = mClient->createSurface(name, w, h, format, flags, parentHandle, std::move(metadata),
                                     &handle, &gbp, &id, &transformHint);
​
        if (outTransformHint) {
            *outTransformHint = transformHint;
        }
        ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err));
        if (err == NO_ERROR) {
            *outSurface =
                    new SurfaceControl(this, handle, gbp, id, w, h, format, transformHint, flags);
        }
    }
    return err;
}
构造函数
css 复制代码
SurfaceComposerClient::SurfaceComposerClient()
    : mStatus(NO_INIT)
{
}
onFirstRef
ini 复制代码
//构造调用
void SurfaceComposerClient::onFirstRef() {
    //这里就是binder 调用 SF
    sp<ISurfaceComposer> sf(ComposerService::getComposerService());
    if (sf != nullptr && mStatus == NO_INIT) {
      //跨进程调用SF的createConnection
        sp<ISurfaceComposerClient> conn;
        conn = sf->createConnection(); //调用到 SurfaceFlinger 的 createConnection
        if (conn != nullptr) {
            mClient = conn;
            mStatus = NO_ERROR;
        }
    }
}

总体串联

串联Activity->ViewRootImp

scss 复制代码
ActivityThread.handleResumeActivity()
-->wm.addView(decor, l);
-->WindowManagerImp.addView()
-->mGlobal.addView(view, params, mContext.getDisplayNoVerify(), mParentWindow,
                mContext.getUserId());
-->WindowManagerGlobal.addView()
-->  root = new ViewRootImpl(view.getContext(), display);//创建ViewRootImo
-->root.setView()
...
​

surface的创建流程

scss 复制代码
ViewRootImp-->
//(详情看ViewRootImp的方法和属性)
-->setView()
   --> requestLayout();
      -->...doTraversal()-->performTraversals();
      --> relayoutResult = relayoutWindow(mWindow, params,widhth,height..mSurfaceControl)
        //将内部surfaceControl,宽高,参数 传递给wms
      -->mWindowSession.relayout(...)
      -->Aidl调用Session.relayout(...)
       -->WindowManagerService.relayoutWindow(...attrs,..outSurfaceControl,)
       --> createSurfaceControl(outSurfaceControl, result, win, winAnimator)
       -->surfaceController = winAnimator.createSurfaceLocked(win.mAttrs.type);
          -->WindowStateAnimator.createSurfaceLocked//WindowStateAnimator 对应方法
           --> 不为null返回mSurfaceController 
             -->null调用 返回 new WindowSurfaceController() 
               --> 调用SurfaceControl.Builder.build()
               --> new SurfaceControl(
                    mSession, mName, mWidth, mHeight, mFormat, mFlags, mParent, mMetadata,
                    mLocalOwnerView, mCallsite);
               -->  mNativeObject = nativeCreate(session, name, w, h, format, flags,
                    parent != null ? parent.mNativeObject : 0, metaParcel);
                   -->android_view_SurfaceControl.cpp.nativeCreate()
                     -->client->createSurfaceChecked()//具体看android_view_SurfaceControl.cpp
                     --> 返回
        -->surfaceController.getSurfaceControl(outSurfaceControl)//c++层创建的mSurfaceControl   拷贝到ViewTRootImp 传递过来的outSurfaceControl
         
     
---------------------------------------------------------
   --> mWindowSession.addToDisplayAsUser()
       -->Aidl调用Session.addToDisplayAsUser()
       --> mService.addWindow()
       --> 创建windowState 调用attach() 
       -->Session.windowAddedLocked();//将surfaceSession 创建 并 wms管理当前Session 也就是当前app唯一的Session
       --> mSurfaceSession = new SurfaceSession();
           mService.mSessions.add(this);
           mNumWindow++;
          --> SurfaceSession 构造函数   mNativeClient = nativeCreate();
          -->android_view_SurfaceSession.cpp  -->nativeCreate()//创建SurfaceComposerClient 返回 可以理解为 SF的在APP端的代理  这里会有疑问,为什么这个代码在下面,因为上面的 performTraversals 需要监听到 SF 的callBack 才会执行,这会就已经初始化完成了
           
    -->     
        

SF在C端的创建流程

SF的创建在 SurfaceSession 的构造函数里,Session就是会话的意思

scss 复制代码
android_view_SurfaceSession.cpp
  -->nativeCreate()
  ---> SurfaceComposerClient* client = new SurfaceComposerClient();
​
 ...
   --> 首次会调用 SurfaceComposerClient的onFirstRef 方法  调用sf->createConnection()
   --> SurFaceFlinger.createConnection()
​
   --> 创建一个 Client 返回
   sp<ISurfaceComposerClient> SurfaceFlinger::createConnection() {
    const sp<Client> client = new Client(this);
    return client->initCheck() == NO_ERROR ? client : nullptr;
}

view 如何转化到屏幕上的?

核心类

ThreadedRenderer
scss 复制代码
ViewRootImp.draw()
->mAttachInfo.mThreadedRenderer.draw(mView, mAttachInfo, this);
-->ThreadRenderer.draw()
   -->updateRootDisplayList(view, callbacks);
       --> updateViewTreeDisplayList(view);
       --> view.updateDisplayListIfDirty();//渲染自己的Node View方法 最终返回RenDerNode
          --> if (renderNode.hasDisplayList(){  dispatchGetDisplayList(); //遍历子节点 ViewGroup }
                                              
   -->registerAnimatingRenderNode()//方法注册动画 Render Node
   -->syncAndDrawFrame()//通知RenderThread 渲染下一帧
RecordingCanvas
ini 复制代码
//真正的绘制 RecordingCanvas  绘图指令员
if (mRootNodeNeedsUpdate || !mRootNode.hasDisplayList()) {
            RecordingCanvas canvas = mRootNode.beginRecording(mSurfaceWidth, mSurfaceHeight);
            try {
                final int saveCount = canvas.save();
                canvas.translate(mInsetLeft, mInsetTop);
                callbacks.onPreDraw(canvas);
​
                canvas.enableZ();
                canvas.drawRenderNode(view.updateDisplayListIfDirty());
                canvas.disableZ();
​
                callbacks.onPostDraw(canvas);
                canvas.restoreToCount(saveCount);
                mRootNodeNeedsUpdate = false;
            } finally {
                mRootNode.endRecording();
            }
        }
RenderNode

会包含DisPlayList ,DisPlayList里面也可能包含RenderNode,套娃。

真正的绘制者
scss 复制代码
performTraversals()-->performDraw();
-->....-> CanvasContext.draw()
​
CanvasContext.cpp
ini 复制代码
Frame frame = mRenderPipeline->getFrame();
SkRect windowDirty = computeDirtyRect(frame, &dirty);
​
bool drew = mRenderPipeline->draw(frame, windowDirty, dirty, mLightGeometry, &mLayerUpdateQueue,
                                  mContentDrawBounds, mOpaque, mLightInfo, mRenderNodes,
                                  &(profiler()));
总结

Surface 拥有一个buffer,但是buffer不能直接给屏幕用,就需要提交给SF的队列,SF处理后再给屏幕

在这个过程中,屏幕用完这个buffer 会再次还给SF,避免消耗。

常见问题题梳理

  • 图层面板是什么?

android 里每个Activity都有一个独立的画布,应用端叫surface 在

SF里叫layer, 无论多么复杂的view解构 其实都是画在了所在的Activity

上。

  • 为什么设计成C/S架构

避免崩溃 影响系统服务。

  • buffer是什么

buffer缓存了图形的内存空间,被surface管理

  • Surface 对其他逻辑的影响

Surface画布的影响 到Window窗口的大小,影响wms 服务的控制大小,(更新window)

相关推荐
openinstall全渠道统计3 小时前
免填邀请码工具:赋能六大核心场景,重构App增长新模型
android·ios·harmonyos
双鱼大猫3 小时前
一句话说透Android里面的ServiceManager的注册服务
android
双鱼大猫3 小时前
一句话说透Android里面的查找服务
android
双鱼大猫3 小时前
一句话说透Android里面的SystemServer进程的作用
android
双鱼大猫3 小时前
一句话说透Android里面的View的绘制流程和实现原理
android
双鱼大猫4 小时前
一句话说透Android里面的Window的内部机制
android
双鱼大猫5 小时前
一句话说透Android里面的为什么要设计Window?
android
双鱼大猫5 小时前
一句话说透Android里面的主线程创建时机,frameworks层面分析
android
苏金标5 小时前
android 快速定位当前页面
android
雾里看山8 小时前
【MySQL】内置函数
android·数据库·mysql