前言
一个窗口里面的所有的普通View都会共享一个Surface,这个Surface保存在ViewRootImpl里面。但是SurfaceView不同,SurfaceView自己独享一个Surface,也就意味着每次刷新SurfaceViewUI的时候,可以不必通知ViewRootImpl,这样会大大提高绘制效率。
当然SurfaceView本身也是继承View的,都在一个View Hierarchy中,所以自然也会遵循View的绘制流程。不过SurfaceView自身调用了setWillNotDraw(true)方法,所以本身是不会调用onDraw的。接下来我们就开始往下探究SurfaceView的Surface到底是怎么创建的:
public final class ViewRootImpl implements ViewParent,
View.AttachInfo.Callbacks, ThreadedRenderer.DrawCallbacks {
private void performTraversals() {
// cache mView since it is used so much below...
final View host = mView;
...代码省略...
if (viewVisibilityChanged) {
mAttachInfo.mWindowVisibility = viewVisibility;
host.dispatchWindowVisibilityChanged(viewVisibility);
if (viewUserVisibilityChanged) {
host.dispatchVisibilityAggregated(viewVisibility == View.VISIBLE);
}
if (viewVisibility != View.VISIBLE || mNewSurfaceNeeded) {
endDragResizing();
destroyHardwareResources();
}
if (viewVisibility == View.GONE) {
// After making a window gone, we will count it as being
// shown for the first time the next time it gets focus.
mHasHadWindowFocus = false;
}
}
...代码省略...
}
}
ViewRootImpl#performTraversals这个方法应该都比较熟悉了,每次View请求重新测量或者绘制的时候都会执行这个方法,另外View刚被添加到ViewTree的时候也会执行一次。
这里当当前窗口的可见性发生了变化,就会执行host.dispatchWindowVisibilityChanged方法,这里的host是ViewRootImpl 的mView成员变量,也就是一个窗口中最顶层的View——DecorView,DecorView继承了ViewGroup,自身并没有重写dispatchWindowVisibilityChanged方法,所以进入ViewGroup看下:
@Override
public void dispatchWindowVisibilityChanged(int visibility) {
super.dispatchWindowVisibilityChanged(visibility);
final int count = mChildrenCount;
final View[] children = mChildren;
for (int i = 0; i < count; i++) {
children[i].dispatchWindowVisibilityChanged(visibility);
}
}
这里面就是调用了所有子View的dispatchWindowVisibilityChanged:
/**
* Dispatch a window visibility change down the view hierarchy.
* ViewGroups should override to route to their children.
*
* @param visibility The new visibility of the window.
*
* @see #onWindowVisibilityChanged(int)
*/
public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
onWindowVisibilityChanged(visibility);
}
View中调用的onWindowVisibilityChanged方法,既然我们今天的主角是SurfaceView,那就去看SurfaceView是如何重写这个方法的:
@Override
protected void onWindowVisibilityChanged(int visibility) {
super.onWindowVisibilityChanged(visibility);
mWindowVisibility = visibility == VISIBLE;
updateRequestedVisibility();
updateSurface();
}
这里需要重点说下updateSurface这个核心方法:
/** @hide */
protected void updateSurface() {
//判断SurfaceView的宿主窗口的大小是否已经计算好了,
//SurfaceView必须在宿主窗口大小计算完毕之后才能更新
if (!mHaveFrame) {
return;
}
ViewRootImpl viewRoot = getViewRootImpl();
...代码省略...
//检查surfaceview是否存在变化
if (creating || formatChanged || sizeChanged || visibleChanged || windowVisibleChanged) {
getLocationInWindow(mLocation);
if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
+ "Changes: creating=" + creating
+ " format=" + formatChanged + " size=" + sizeChanged
+ " visible=" + visibleChanged
+ " left=" + (mWindowSpaceLeft != mLocation[0])
+ " top=" + (mWindowSpaceTop != mLocation[1]));
try {
...代码省略...
if (creating) {
//创建SurfaceSession
mSurfaceSession = new SurfaceSession(viewRoot.mSurface);
mDeferredDestroySurfaceControl = mSurfaceControl;
updateOpaqueFlag();
通过SurfaceSession创建SurfaceControl
mSurfaceControl = new SurfaceControlWithBackground(mSurfaceSession,
"SurfaceView - " + viewRoot.getTitle().toString(),
mSurfaceWidth, mSurfaceHeight, mFormat,
mSurfaceFlags);
} else if (mSurfaceControl == null) {
return;
}
boolean realSizeChanged = false;
mSurfaceLock.lock();
try {
mDrawingStopped = !visible;
if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
+ "Cur surface: " + mSurface);
SurfaceControl.openTransaction();
try {
//设置Layer属性
mSurfaceControl.setLayer(mSubLayer);
...代码省略...
} finally {
SurfaceControl.closeTransaction();
}
if (sizeChanged || creating) {
redrawNeeded = true;
}
...代码省略...
} finally {
mSurfaceLock.unlock();
}
try {
...代码省略...
if (creating) {
//mSurface从mSurfaceControl中拷贝出GraphicBufferProducer
mSurface.copyFrom(mSurfaceControl);
}
...代码省略...
} catch (Exception ex) {
Log.e(TAG, "Exception configuring surface", ex);
}
...代码省略...
}
}
- 这里我们首先从创建SurfaceSession开始:
public final class SurfaceSession {
// Note: This field is accessed by native code.
private long mNativeClient; // SurfaceComposerClient*
private static native long nativeCreate();
private static native long nativeCreateScoped(long surfacePtr);
private static native void nativeDestroy(long ptr);
private static native void nativeKill(long ptr);
/** Create a new connection with the surface flinger. */
public SurfaceSession() {
mNativeClient = nativeCreate();
}
public SurfaceSession(Surface root) {
mNativeClient = nativeCreateScoped(root.mNativeObject);
}
/* no user serviceable parts here ... */
@Override
protected void finalize() throws Throwable {
try {
if (mNativeClient != 0) {
nativeDestroy(mNativeClient);
}
} finally {
super.finalize();
}
}
/**
* Forcibly detach native resources associated with this object.
* Unlike destroy(), after this call any surfaces that were created
* from the session will no longer work.
*/
public void kill() {
nativeKill(mNativeClient);
}
}
SurfaceSession本身代码量非常少,在构造方法中调用了nativeCreateScoped(root.mNativeObject)方法,那么就进入对应的cpp文件看下具体实现:
frameworks/base/core/jni/android_view_SurfaceSession.cpp
static jlong nativeCreateScoped(JNIEnv* env, jclass clazz, jlong surfaceObject) {
Surface *parent = reinterpret_cast(surfaceObject);
SurfaceComposerClient* client = new SurfaceComposerClient(parent->getIGraphicBufferProducer());
client->incStrong((void*)nativeCreate);
return reinterpret_cast(client);
}
这里创建了SurfaceComposerClient对象,调用了SurfaceComposerClient的父类方法IncStrong,内部会调用SurfaceComposerClient#onFirstRef方法
/frameworks/native/libs/gui/SurfaceComposerClient.cpp
void SurfaceComposerClient::onFirstRef() {
//获取SurfacFlinger的代理BpSurfaceComposer
sp sf(ComposerService::getComposerService());
if (sf != 0 && mStatus == NO_INIT) {
auto rootProducer = mParent.promote();
sp conn;
conn = (rootProducer != nullptr) ? sf->createScopedConnection(rootProducer) :
sf->createConnection();
if (conn != 0) {
mClient = conn;
mStatus = NO_ERROR;
}
}
}
调用BpSurfaceComposer的createScopedConnection方法,然后通过Binder调用SurfaceFlinger的createScopedConnection
sp SurfaceFlinger::createScopedConnection(
const sp& gbp) {
if (authenticateSurfaceTexture(gbp) == false) {
return nullptr;
}
const auto& layer = (static_cast(gbp.get()))->getLayer();
if (layer == nullptr) {
return nullptr;
}
return initClient(new Client(this, layer));
}
创建对应的BpSurfaceComposerClient,然后将Client返回给Java层的SurfaceSession,并赋值给mNativeClient.
- 然后我们再来看下SurfaceControl的创建过程
mSurfaceControl = new SurfaceControlWithBackground(mSurfaceSession,
"SurfaceView - " + viewRoot.getTitle().toString(),
mSurfaceWidth, mSurfaceHeight, mFormat,
mSurfaceFlags);
咱们重新回到updateSurface方法中,此处初始化了SurfaceControl,将SurfaceSession传进去,再来看下构造方法里面都做了什么操作
public SurfaceControlWithBackground(SurfaceSession s,
String name, int w, int h, int format, int flags)
throws Exception {
super(s, name, w, h, format, flags);
mBackgroundControl = new SurfaceControl(s, "Background for - " + name, w, h,
PixelFormat.OPAQUE, flags | SurfaceControl.FX_SURFACE_DIM);
mOpaque = (flags & SurfaceControl.OPAQUE) != 0;
}
public SurfaceControl(SurfaceSession session,
String name, int w, int h, int format, int flags)
throws OutOfResourcesException {
this(session, name, w, h, format, flags, null, INVALID_WINDOW_TYPE, Binder.getCallingUid());
}
public SurfaceControl(SurfaceSession session, String name, int w, int h, int format, int flags,
SurfaceControl parent, int windowType, int ownerUid)
throws OutOfResourcesException {
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;
mNativeObject = nativeCreate(session, name, w, h, format, flags,
parent != null ? parent.mNativeObject : 0, windowType, ownerUid);
if (mNativeObject == 0) {
throw new OutOfResourcesException(
"Couldn't allocate SurfaceControl native object");
}
mCloseGuard.open("release");
}
SurfaceControlWithBackground的构造方法主要调用了父类的构造方法,然后父类SurfaceControl中调用了nativeCreate方法,那么再次进入C++层看下那提测Create的处理逻辑:
frameworks\native\services\surfaceflinger\ android_view_SurfaceControl.cpp
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 client(android_view_SurfaceSession_getClient(env, sessionObj));
SurfaceControl *parent = reinterpret_cast(parentObject);
//client为SurfaceComposerClient对象
sp surface;
status_t err = client->createSurfaceChecked(
String8(name.c_str()), w, h, format, &surface, flags, parent, windowType, ownerUid);
...代码省略...
//增加SurfaceControl的引用计数
surface->incStrong((void *)nativeCreate);
//获取IGraphicBufferProducer对象
return reinterpret_cast(surface.get());
}
首先通过sessionObj获取SurfaceComposerClient的代理对象BpSurfaceComposerClient,然后通过SurfaceComposerClient创建Surface
frameworks\native\libs\gui\SurfaceComposerClient.cpp
status_t SurfaceComposerClient::createSurfaceChecked(
const String8& name,
uint32_t w,
uint32_t h,
PixelFormat format,
sp* outSurface,
uint32_t flags,
SurfaceControl* parent,
int32_t windowType,
int32_t ownerUid)
{
sp sur;
status_t err = mStatus;
if (mStatus == NO_ERROR) {
sp handle;
sp parentHandle;
sp gbp;
if (parent != nullptr) {
parentHandle = parent->getHandle();
}
err = mClient->createSurface(name, w, h, format, flags, parentHandle,
windowType, ownerUid, &handle, &gbp);
ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err));
if (err == NO_ERROR) {
*outSurface = new SurfaceControl(this, handle, gbp, true /* owned */);
}
}
return err;
}
此处mClient是在刚才创建SurfaceSession的时候生成的,SurfaceFlinger为BnSurfaceComposerClient创建的一个代理对象即BpSurfaceComposerClient对象。然后调用对应的createSurface方法,如果没有出现错误,那么就直接创建出SurfaceControl。那么我们再看下createSurface的逻辑:
frameworks\native\services\surfaceflinger\Client.cpp
status_t Client::createSurface(
const String8& name,
uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
const sp& parentHandle, int32_t windowType, int32_t ownerUid,
sp* handle,
sp* gbp)
{
...代码省略...
sp msg = new MessageCreateLayer(mFlinger.get(),
name, this, w, h, format, flags, handle,
windowType, ownerUid, gbp, &parent);
mFlinger->postMessageSync(msg);
return static_cast( msg.get() )->getResult();
}
这里通过跨进程的RPC通信,调用SurfaceFlinger进程的createLayer方法:
frameworks\native\services\surfaceflinger\SurfaceFlinger.cpp
status_t SurfaceFlinger::createLayer(
const String8& name,
const sp& client,
uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
int32_t windowType, int32_t ownerUid, sp* handle,
sp* gbp, sp* parent)
{
...代码省略...
status_t result = NO_ERROR;
sp layer;
String8 uniqueName = getUniqueLayerName(name);
switch (flags & ISurfaceComposerClient::eFXSurfaceMask) {
case ISurfaceComposerClient::eFXSurfaceNormal:
result = createBufferLayer(client,
uniqueName, w, h, flags, format,
handle, gbp, &layer);
break;
case ISurfaceComposerClient::eFXSurfaceColor:
result = createColorLayer(client,
uniqueName, w, h, flags,
handle, &layer);
break;
default:
result = BAD_VALUE;
break;
}
...代码省略...
//将client和Layer关联起来,把Layer添加到client的mLayers集合里面去
result = addClientLayer(client, *handle, *gbp, layer, *parent);
if (result != NO_ERROR) {
return result;
}
mInterceptor->saveSurfaceCreation(layer);
setTransactionFlags(eTransactionNeeded);
return result;
}
此处调用createNormalLayer创建layer,然后将Layer与client关联起来。SurfaceFlinger里的Layer对应的就是Java层的Surface。
所以初始化SurfaceControl的时候就是创建了一个SurfaceControl,并让SurfaceFlinger创建了一个对应的Layer。
- 接下来就重新回到java层,再来看下初始化完SurfaceControl以后,就将SurfaceControl的GraphicBufferProducer copy给mSurface对象
if (creating) {
mSurface.copyFrom(mSurfaceControl);
}
至此,Surface就创建完毕了,下一节再讲SurfaceView是如何"挖洞"的
总结
SurfaceView创建Surface主要的过程如下:
- 首先创建SurfaceSession,这个时候返回一个SurfaceComposeClient的指针给java层
- SurfaceComposeClient在创建的时候,会获取SurfaceFlinger的代理对象BpSurfaceComposer,通过该对象在SurfaceFlinger中创建BnSurfaceComposerClient对象。并且将该对象创建BpSurfaceComposerClient对象赋值给了SurfaceComposeClient的mClient
- 然后创建SurfaceControl,获取SurfaceComposeClient的代理对象BpSurfaceComposeClient,由改对象调用createSurface通过RPC通信调用到SurfaceFlinger的createSurface方法
- 创建Layer对象
- 将SurfaceControl拷贝给mSurface对象,copy过程中创建对应的Surface对象,然后将C++层的Surface赋值给Java层的Surface对象的mNativeObject