基础概念梳理
个人理解
在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)