SurfaceFlinger和端侧的大体框架
简述
这篇博客会带大家探究app和WMS是怎么通过binder和SurfaceFlinger进行通信,主要围绕如何基于Binder去创建一个Surface来展开。
Binder是一个Android用于跨进程通信的方案,在Android中使用非常多,后面会专门写一个关于Binder专题,在阅读这篇文章之前,只要知道java和c++分别是怎么使用binder的就可以了。
WMS(WindowManagerService)是Android中的窗口管理服务,用来管理所有app创建的窗口,比如管理窗口Z轴顺序,窗口大小位置,窗口动画等等。app创建窗口一般会通过binder通知WMS,WMS再和SurfaceFlinger通信创建窗口,在WMS中会为一个窗口构建一个SurfaceControl类,并且会将创建完成的窗口返回给app,我们在app内的窗口渲染相关的逻辑会抽象在一个Surface类里,Surface可以提供对窗口绘制渲染的接口,SurfaceControl提供了对窗口的控制能力,比如修改窗口大小位置等。这样app就只能绘制窗口,想要修改窗口的属性就要通过WMS。 关于WMS后面会有一个专门的专题来介绍,这里只要知道他的大概理念即可。
app创建窗口
app创建窗口时,最终会调用到WMS的addWindow,经过一系列调用最终会构建一个WindowSurfaceController,在里面会构建SurfaceControl,这之间的过程后面在WMS的章节里会介绍,这里就不多赘述了。
1.1 在构造函数里通过Builder构造SurfaceControl
WindowSurfaceController(String name, int format, int flags, WindowStateAnimator animator,
int windowType) {
// ... 省略无关代码
// 构建SurfaceControl
final SurfaceControl.Builder b = win.makeSurface()
.setParent(win.getSurfaceControl())
.setName(name)
.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();
}
1.2 java层SurfaceControl的构造函数,SurfaceControl在c++层也有一个对应的类,他们是一对一的,这里会调用nativeCreate构造c++层对象,返回新建的c++层SurfaceControl的地址,记录到nativeObject,这样java层和c++层到SurfaceControl就一对一关联了。
private SurfaceControl(SurfaceSession session, String name, int w, int h, int format, int flags,
SurfaceControl parent, SparseIntArray metadata, WeakReference<View> localOwnerView,
String callsite)
throws OutOfResourcesException, IllegalArgumentException {
//。。。省略部分代码
try {
//。。。省略部分代码
// 构造对应native对象,返回的是c++层的SurfaceContorl地址,记录地址后就实现关联了
nativeObject = nativeCreate(session, name, w, h, format, flags,
parent != null ? parent.mNativeObject : 0, metaParcel);
} finally {
metaParcel.recycle();
}
// 。。。
// nativeObject是native对象key,通过这个值可以找到对应native对象,这里把它记录到java层的变量里
assignNativeObject(nativeObject, callsite);
}
1.3 对应c++逻辑在android_view_SurfaceControl.cpp内
这里的sessionObj参数是SurfaceSession,SurfaceComposerClient是和SufraceFlinger进行Binder通信的Client端的封装。
这里主要是构造SurfaceComposerClient,然后调用createSurfaceChecked
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;
// SurfaceComposerClient的地址在SurfaceSession中有缓存,这里就是判断一下是否已经构建了
if (sessionObj != NULL) {
client = android_view_SurfaceSession_getClient(env, sessionObj);
} else {
// 第一次构建走这里
// 具体查看1.3.1
client = SurfaceComposerClient::getDefault();
}
// 这里是java侧传过来的父SurfaceControl
SurfaceControl *parent = reinterpret_cast<SurfaceControl*>(parentObject);
sp<SurfaceControl> surface;
// 。。。
sp<IBinder> parentHandle;
if (parent != nullptr) {
parentHandle = parent->getHandle();
}
//调用SurfaceComposerClient.createSurfaceChecked做创建相关的逻辑
// 创建窗口,并且构造一个c++层的SurfaceControl,会通过surface参数返回,具体查看1.4
status_t err = client->createSurfaceChecked(String8(name.c_str()), w, h, format, &surface,
flags, parentHandle, std::move(metadata));
// 。。。
// 返回c++层的SurfaceControl地址,java层会记录这个地址相互关联
return reinterpret_cast<jlong>(surface.get());
}
1.3.1 SurfaceComposerClient::getDefault()
构建SurfaceComposerClient
sp<SurfaceComposerClient> SurfaceComposerClient::getDefault() {
// 查看1.3.2
return DefaultComposerClient::getComposerClient();
}
1.3.2 DefaultComposerClient::getComposerClient()
static sp<SurfaceComposerClient> getComposerClient() {
// 这里是个单例
DefaultComposerClient& dc = DefaultComposerClient::getInstance();
Mutex::Autolock _l(dc.mLock);
if (dc.mClient == nullptr) {
// 调用SurfaceComposerClient构造,赋值给智能指针,具体查看1.3.3
dc.mClient = new SurfaceComposerClient;
}
return dc.mClient;
}
1.3.3 void SurfaceComposerClient::onFirstRef()
智能指针首次赋值时会调用类的onFirstRef,这里首先通过ServiceManager获取SurfaceFlinger binder服务的handle,想要访问binder服务都必须要有这个服务的handle,服务启动时候会告诉ServiceManager自己的handle,并且和一个固定的字符串进行绑定,后面其他进程想要访问这个binder服务就可以通过固定的字符串去和ServiceManager查询这个handle。
其他进程也是通过binder访问ServiceManager的,这时候就有个问题,那其他进程是怎么获取ServiceManager的handle呢,其实很简单,ServiceManager的handle是固定的。其他细节在专门介绍binder的章节来解释,这里只要知道它的接口是这么用的就行。
拿到SurfaceFlinger的binder就可以和SurfaceFlinger进行通信了,调用了binder接口createConnection来创建了一个Client对象并记录下来了。
void SurfaceComposerClient::onFirstRef() {
// 连接SurfaceFlingerAIDL的binder,详见1.3.3.1
sp<gui::ISurfaceComposer> sf(ComposerServiceAIDL::getComposerService());
if (sf != nullptr && mStatus == NO_INIT) {
sp<ISurfaceComposerClient> conn;
// 通过binder接口调用createConnection,创建和surfaceflinger的连接,详见1.3.4
binder::Status status = sf->createConnection(&conn);
if (status.isOk() && conn != nullptr) {
// 返回的Client记录在这里
mClient = conn;
mStatus = NO_ERROR;
}
}
}
1.3.3.1 ComposerService::getComposerService()
调用connectLocked创建连接
sp<ISurfaceComposer> ComposerService::getComposerService() {
ComposerService& instance = ComposerService::getInstance();
Mutex::Autolock _l(instance.mLock);
if (instance.mComposerService == nullptr) {
// 这里创建连接,相见1.3.3.2
if (ComposerService::getInstance().connectLocked()) {
ALOGD("ComposerService reconnected");
}
}
return instance.mComposerService;
}
1.3.3.2 ComposerService::connectLocked()
获取SurfaceFinger aidl binder,之后就可以通过它和SurfaceFlinger进行通信了
bool ComposerServiceAIDL::connectLocked() {
//通过AMS查询SurfaceFlingerAIDL的binder service(即SurfaceFlinger)
//这样就可以和SurfaceFlinger通信了
const String16 name("SurfaceFlingerAIDL");
mComposerService = waitForService<gui::ISurfaceComposer>(name);
if (mComposerService == nullptr) {
return false; // fatal error or permission problem
}
// 。。。注册死亡回调
return true;
}
1.3.4 ISurfaceComposer::createConnection
创建连接,构造一个Client对象,这里已经通过binder来到SurfaceFlinger进程里了。(在看android系统代码的时候,要时刻注意当前代码是在哪个进程,这个是初学者很容易弄混的点)
sp是智能指针,我们后面会单独写一篇文章来解释,这里make方法就是构造一个Client,Client是持有SurfaceFlinger引用的,可以用来访问SurfaceFlinger,然后会把Client返回给WMS进程
binder::Status SurfaceComposerAIDL::createConnection(sp<gui::ISurfaceComposerClient>* outClient) {
// 构造一个Client类,并且通过binder把这个Client返回给客户端进程(WMS)
const sp<Client> client = sp<Client>::make(mFlinger);
if (client->initCheck() == NO_ERROR) {
*outClient = client;
return binder::Status::ok();
} else {
*outClient = nullptr;
return binderStatusFromStatusT(BAD_VALUE);
}
}
到这里为止我们就构建了一个SurfaceComposerClient对象,然后通过binder调用SurfaceFlinger构建了一个持有SurfaceFlinger引用的Client对象。
我们接着看1.3.1后面
1.4 SurfaceComposerClient.createSurfaceChecked
这里调用Client的createSurface让surfaceFlinger创建窗口,然后会返回一些窗口的信息存在result里,result有个handle字段,代表新创建的窗口的句柄。(关于这些handle,可以简单的认为handle就是一个id,可以查询到唯一的目标对象,这样理解后续看代码会简单一些)
然后会构造一个c++层的SurfaceControl,这个和java层是一对一的
status_t SurfaceComposerClient::createSurfaceChecked(const String8& name, uint32_t w, uint32_t h,
PixelFormat format,
sp<SurfaceControl>* outSurface, int32_t flags,
const sp<IBinder>& parentHandle,
LayerMetadata metadata,
uint32_t* outTransformHint) {
sp<SurfaceControl> sur;
status_t err = mStatus;
if (mStatus == NO_ERROR) {
gui::CreateSurfaceResult result;
// 调用上面Client的createSurface让surfaceFlinger创建窗口,具体查看1.5
binder::Status status = mClient->createSurface(std::string(name.string()), flags,
parentHandle, std::move(metadata), &result);
err = statusTFromBinderStatus(status);
if (outTransformHint) {
*outTransformHint = result.transformHint;
}
ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err));
if (err == NO_ERROR) {
// 构建c++层的SurfaceControl,持有窗口的handle,是一个binder对象。
// 构造函数主要就是把这些参数记录到变量里,这里就不看了
*outSurface = new SurfaceControl(this, result.handle, result.layerId,
toString(result.layerName), w, h, format,
result.transformHint, flags);
}
}
return err;
}
1.5 Client::createSurface
这里就是构造一个LayerCreationArgs对象把参数封装一下,然后调用SurfaceFlinger的createLayer创建窗口。之前在简述里提到过,每个窗口在SurfaceFlinger里面对应的就是一个layer。
binder::Status Client::createSurface(const std::string& name, int32_t flags,
const sp<IBinder>& parent, const gui::LayerMetadata& metadata,
gui::CreateSurfaceResult* outResult) {
sp<IBinder> handle;
// 封装参数
LayerCreationArgs args(mFlinger.get(), sp<Client>::fromExisting(this), name.c_str(),
static_cast<uint32_t>(flags), std::move(metadata));
args.parentHandle = parent;
// 调用createLayer创建窗口,详细查看2.1
const status_t status = mFlinger->createLayer(args, *outResult);
return binderStatusFromStatusT(status);
}
SurfaceFlinger创建layer
2.1 SurfaceFlinger::createLayer
通过createBufferStateLayer构造layer对象
关联父layer节点
然后调用addClientLayer做layer的添加
status_t SurfaceFlinger::createLayer(LayerCreationArgs& args, gui::CreateSurfaceResult& outResult) {
status_t result = NO_ERROR;
sp<Layer> layer;
switch (args.flags & ISurfaceComposerClient::eFXSurfaceMask) {
case ISurfaceComposerClient::eFXSurfaceBufferQueue:
case ISurfaceComposerClient::eFXSurfaceContainer:
case ISurfaceComposerClient::eFXSurfaceBufferState:
args.flags |= ISurfaceComposerClient::eNoColorFill;
FMT_FALLTHROUGH;
case ISurfaceComposerClient::eFXSurfaceEffect: {
// 构造layer对象,详见2.1.1
result = createBufferStateLayer(args, &outResult.handle, &layer);
std::atomic<int32_t>* pendingBufferCounter = layer->getPendingBufferCounter();
if (pendingBufferCounter) {
std::string counterName = layer->getPendingBufferCounterName();
mBufferCountTracker.add(outResult.handle->localBinder(), counterName,
pendingBufferCounter);
}
} break;
default:
result = BAD_VALUE;
break;
}
if (result != NO_ERROR) {
return result;
}
args.addToRoot = args.addToRoot && callingThreadHasUnscopedSurfaceFlingerAccess();
// 根据入参关联父layer
sp<Layer> parent = LayerHandle::getLayer(args.parentHandle.promote());
if (args.parentHandle != nullptr && parent == nullptr) {
ALOGE("Invalid parent handle %p", args.parentHandle.promote().get());
args.addToRoot = false;
}
uint32_t outTransformHint;
// 添加layer,详见2.2
result = addClientLayer(args, outResult.handle, layer, parent, &outTransformHint);
if (result != NO_ERROR) {
return result;
}
outResult.transformHint = static_cast<int32_t>(outTransformHint);
outResult.layerId = layer->sequence;
outResult.layerName = String16(layer->getDebugName());
return result;
}
2.1.1 createBufferStateLayer
通过getNewTexture获取一个纹理索引,opengl渲染用的,后面在合成的章节我们再详细介绍
工厂模式构建layer,这里实际调用的是DefaultFactory构建layer,其实里面就是调用了sp::make(args)直接构造了layer对象。layer构造方法里主要是大量的变量初始化,以及构造一个layerFE对象,这些是和合成相关的逻辑我们会在合成的章节再介绍。
status_t SurfaceFlinger::createBufferStateLayer(LayerCreationArgs& args, sp<IBinder>* handle,
sp<Layer>* outLayer) {
// 获取一个纹理索引,opengl渲染需要
args.textureName = getNewTexture();
// 构造layer对象
*outLayer = getFactory().createBufferStateLayer(args);
// 这里是关联layer的binder对象,回传给client侧的。
*handle = (*outLayer)->getHandle();
return NO_ERROR;
}
2.2 addClientLayer
首先判断一下layer是否超过上限,如果超过上限就打印一些日志用于排查问题
然后将需要添加的layer存储到mCreatedLayers里,同时将args构造成RequestedLayerState添加到mNewLayers。实际上这两者只有一个会被用到,具体使用哪个会由一个属性控制,感觉像是版本遗留产物,且这两个容器都是临时存储的中间容器,会在下一个Vsync信号来的时候进行真正的处理。
setTransactionFlags标记需要更新layer,且会在里面注册下一个Vsync信号。
status_t SurfaceFlinger::addClientLayer(LayerCreationArgs& args, const sp<IBinder>& handle,
const sp<Layer>& layer, const wp<Layer>& parent,
uint32_t* outTransformHint) {
if (mNumLayers >= MAX_LAYERS) {
// 。。。
// 如果当前layer数量超过上限,这里主要做一些错误日志的打印,以便排除是否有页面泄漏
return NO_MEMORY;
}
layer->updateTransformHint(mActiveDisplayTransformHint);
if (outTransformHint) {
*outTransformHint = mActiveDisplayTransformHint;
}
// 如果有父layer或者镜像layer,也封装到args参数里
args.parentId = LayerHandle::getLayerId(args.parentHandle.promote());
args.layerIdToMirror = LayerHandle::getLayerId(args.mirrorLayerHandle.promote());
{
// 这里会把当前的layer添加到mCreatedLayers里面去
// 并且通过args构造一个RequestedLayerState对象添加到mNewLayers
// 这两个都是vector,用来临时存储需要添加layer到信息,等到下一个vsync信号SurfaceFlinger才会真的去处理layer的添加。
std::scoped_lock<std::mutex> lock(mCreatedLayersLock);
mCreatedLayers.emplace_back(layer, parent, args.addToRoot);
mNewLayers.emplace_back(std::make_unique<frontend::RequestedLayerState>(args));
args.mirrorLayerHandle.clear();
args.parentHandle.clear();
mNewLayerArgs.emplace_back(std::move(args));
}
// 更新标记位表示更新,并且注册下一个Vsync信号,详见2.3
setTransactionFlags(eTransactionNeeded);
return NO_ERROR;
}
2.3 setTransactionFlags
更新了 mTransactionFlags标记
通过scheduleCommit注册了下一个Vsync信号
void SurfaceFlinger::setTransactionFlags(uint32_t mask, TransactionSchedule schedule,
const sp<IBinder>& applyToken, FrameHint frameHint) {
// Vsync模拟信号参数更新,在Vsync篇章会讲
mScheduler->modulateVsync({}, &VsyncModulator::setTransactionSchedule, schedule, applyToken);
// 更新flag
uint32_t transactionFlags = mTransactionFlags.fetch_or(mask);
ATRACE_INT("mTransactionFlags", transactionFlags);
if (const bool scheduled = transactionFlags & mask; !scheduled) {
// 里面实际调用了mScheduler->scheduleFrame(),注册下一个Vsync
scheduleCommit(frameHint);
} else if (frameHint == FrameHint::kActive) {
mScheduler->resetIdleTimer();
}
}
到下一个Vsync信号,我们SurfaceFlinger侧的layer就创建完成了。接下去看看app侧构建Surface
app侧构建Surface
3.1 WMS在构建完成SurfaceControl之后会把这个SurfaceControl返回给app,app会用这个SurfaceContorl构建SurfaceFlinger,具体代码位置在ViewRootImpl里面,这里流程我们不细说了,主要聚焦和SurfaceFLinger有关系的地方。
WMS会通过mSurfaceControl返回新建的SurfaceContorl。
这里BLAST是Android 12开始的,主要是Surface下面的消费者生产者模型的区别,以前的模型消费者在app进程,而生产者在SurfaceFlinger进程,而现在都在app进程内。
关于BLAST消费者生产者模型后面会有专门的章节来解释。
private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,
boolean insetsPending) throws RemoteException {
// 。。。
// 之前是从这里请求WMS去处理是否需要新增窗口的,SurfaceControl会通过mSurfaceControl返回
relayoutResult = mWindowSession.relayout(mWindow, params,
requestedWidth, requestedHeight, viewVisibility,
insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0, mRelayoutSeq,
mLastSyncSeqId, mTmpFrames, mPendingMergedConfiguration, mSurfaceControl,
mTempInsets, mTempControls, mRelayoutBundle);
// 。。。
if (mSurfaceControl.isValid()) {
// 构建Surface,新版本Android都是使用BLAST的,会走下面
if (!useBLAST()) {
mSurface.copyFrom(mSurfaceControl);
} else {
// 构建Blast模型的Surface,详见3.2
updateBlastSurfaceIfNeeded();
}
// 。。。
}
// 。。。
}
3.2 updateBlastSurfaceIfNeeded
构建消费者生产者模型,然后通过该对象构建Surface,这里其实可以推断出来,Surface和buffer队列关系紧密,Surface提供一些封装的渲染能力,渲染后的数据会存储到这个buffer队列进行消费。关于这个队列我们会有专门的篇章来介绍。
void updateBlastSurfaceIfNeeded() {
if (!mSurfaceControl.isValid()) {
return;
}
if (mBlastBufferQueue != null && mBlastBufferQueue.isSameSurfaceControl(mSurfaceControl)) {
mBlastBufferQueue.update(mSurfaceControl,
mSurfaceSize.x, mSurfaceSize.y,
mWindowAttributes.format);
return;
}
if (mBlastBufferQueue != null) {
mBlastBufferQueue.destroy();
}
// 首次走这里,构建消费者生产者队列模型。
mBlastBufferQueue = new BLASTBufferQueue(mTag, mSurfaceControl,
mSurfaceSize.x, mSurfaceSize.y, mWindowAttributes.format);
mBlastBufferQueue.setTransactionHangCallback(sTransactionHangCallback);
// 构建Surface
Surface blastSurface = mBlastBufferQueue.createSurface();
mSurface.transferFrom(blastSurface);
}
小结
我们通过这边文章主要介绍了app通过WMS是怎么构建了SurfaceContorl,和SurfaceFLinger通信,并且在SufraceFLinger侧构建了一个layer对象。然后app侧通过SurfaceContorl去构建Surface,引出了BlastBufferQueue。