基础概念梳理
个人了解
在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
特点
//空的结构 其实只是个占位后期需求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
//结构函数获取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 会调用如下两个办法
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);
//调用Session的addToDisplayAsUser 实践是调用了wms的addWindow
res = mWindowSession.addToDisplayAsUser(mWindow, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(), userId, mInsetsController.getRequestedVisibility(), inputChannel, mTempInsets,
mTempControls);
Surface.java
copyFrom()
@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
@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
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
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()
//中心代码 创立WindowState 并调用 attach
final WindowState win = new WindowState(this, session, client, token, parentWindow,
appOp[0], attrs, viewVisibility, session.mUid, userId,
session.mCanAddInternalSystemWindow);...
win.attach();
relayoutWindow
//申请宽高
if (viewVisibility != View.GONE) { win.setRequestedSize(requestedWidth, requestedHeight);}
attrChanges = win.mAttrs.copyFrom(attrs);
//将viewRootimp 里边的 outSurfaceControl 传入办法开端创立
result = createSurfaceControl(outSurfaceControl, result, win, winAnimator);
createSurfaceControl
//调用winAnimator
surfaceController = winAnimator.createSurfaceLocked(win.mAttrs.type);
// copyFrom 赋值给viewRootImp里的SurfaceControl
surfaceController.getSurfaceControl(outSurfaceControl);
WindowState.java
attach()
void attach() {
if (DEBUG) Slog.v(TAG, "Attaching " + this + " token=" + mToken);
mSession.windowAddedLocked();
}
SurfaceSession.java
结构函数
public SurfaceSession() {
mNativeClient = nativeCreate();
}
WindowStateAnimator.java
createSurfaceLocked
//假如不为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,
int flags, WindowStateAnimator animator, int windowType)
//会调用到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
多结构参数办法
mNativeObject = nativeCreate(session, name, w, h, format, flags,
parent != null ? parent.mNativeObject : 0, metaParcel);
build()
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
void getSurfaceControl(SurfaceControl outSurfaceControl) {
outSurfaceControl.copyFrom(mSurfaceControl, "WindowSurfaceController.getSurfaceControl");
}
android_view_surfaceControl.cpp
nativeCreate()
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()
static jlong nativeCreate(JNIEnv* env, jclass clazz) {
SurfaceComposerClient* client = new SurfaceComposerClient();
client->incStrong((void*)nativeCreate);
return reinterpret_cast<jlong>(client);
}
register_android_view_SurfaceSession
//其实从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()
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;
}
结构函数
SurfaceComposerClient::SurfaceComposerClient()
: mStatus(NO_INIT)
{
}
onFirstRef
//结构调用
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
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的创立流程
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便是会话的意思
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
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
//真实的制作 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,套娃。
真实的制作者
performTraversals()-->performDraw();
-->....-> CanvasContext.draw()
-
CanvasContext.cpp
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)