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)

相关推荐
枯骨成佛29 分钟前
Android中Crash Debug技巧
android
kim56596 小时前
android studio 更改gradle版本方法(备忘)
android·ide·gradle·android studio
咸芝麻鱼6 小时前
Android Studio | 最新版本配置要求高,JDK运行环境不适配,导致无法启动App
android·ide·android studio
无所谓จุ๊บ6 小时前
Android Studio使用c++编写
android·c++
csucoderlee6 小时前
Android Studio的新界面New UI,怎么切换回老界面
android·ui·android studio
kim56596 小时前
各版本android studio下载地址
android·ide·android studio
饮啦冰美式6 小时前
Android Studio 将项目打包成apk文件
android·ide·android studio
夜色。7 小时前
Unity6 + Android Studio 开发环境搭建【备忘】
android·unity·android studio
ROCKY_8178 小时前
AndroidStudio-滚动视图ScrollView
android
趴菜小玩家9 小时前
使用 Gradle 插件优化 Flutter Android 插件开发中的 Flutter 依赖缺失问题
android·flutter·gradle