前言
在上一篇文章中,对Layer的创建流程进行了分析。Layer创建完成后,根节点或Parent Layer是保存在SurfaceFlinger类中的mCurrentState.layersSortedByZ
和mDrawingState.layersSortedByZ
列表中,而子Layer则是保存在对应Parent Layer的mCurrentChildren
和mDrawingChildren
列表中。
同时,在客户端SurfaceControl对象中持有sp引用,LayerHandle中持有sp引用,因此客户端通过操作LayerHandle就能找到与之对应的Layer。
当SurfaceControl销毁时,对应sp在引用数清零后开始析构,从而触发sp 的引用计数减一。当sp 引用数清零后,便会对Layer进行析构,完成Layer的销毁。
在这个过程中,如果sp持有数太多,则会出现SurfaceControl销毁但Layer没有销毁的场景,此时将导致Layer的泄漏。
surfaceflinger中规定最多只能创建4096个Layer,一旦存留过多,会导致性能变差,带来内存不足、卡顿、发热等问题。所以当业务进程不再使用Layer时,要即时释放销毁,避免出现Layer泄漏问题而影响性能、稳定性。
本篇文章中,将对Layer的整个销毁流程进行说明总结。
Layer的整个销毁流程分为三步:SurfaceControl销毁 -> LayerHandle销毁 -> Layer销毁。
一、SurfaceControl销毁
SurfaceControl销毁有两种方式:
- 调用
SurfaceControl.release()
方法
该方法可以销毁客户端SurfaceControl对象,并将其内部的LayerHandle引用计数减一,但并不一定会保证surfaceflinger进程内的LayerHandle、Layer对象也同步销毁,还要取决于该LayerHandle是否被其他SurfaceControl引用,以及Layer是否存在Parent Layer。
如果对应Layer存在Parent,当客户端对应SurfaceControl销毁时,并不会将Layer同步进行析构,这是因为在Parent Layer中还持有子Layer的强指针引用(sp)。在当其Parent释放时,才会进行析构和销毁。
如果希望对应Layer立即销毁,需要先调用SurfaceControl.Transaction.reparent(null)
方法将其Parent置空后,再执行release();
- 调用
SurfaceControl.Transaction.remove(SurfaceControl sc)
方法。
该方法会对客户端和服务端资源同时进行释放,其内部结合了以上提到的两方法:
java
public Transaction remove(@NonNull SurfaceControl sc) {
// 先将Parent设置为null
reparent(sc, null);
// 再进行release操作
sc.release();
return this;
}
因此,当释放SurfaceControl后,为确保Layer能正常销毁,必须至少满足:
所有引用该Layer对应LayerHandle的SurfaceControl对象全部通过SurfaceControl.release()
释放、且通过SurfaceControl.reparent(null)
将其父Layer置空。
理想情况下,如果一个Parent为空的SurfaceControl执行其release()
方法后,surfaceflinger中对应的LayerHandle、Layer会依次释放和析构,反之,如果Parent不为空,则仅释放析构LayerHandle,Layer不会析构。
1.1、SurfaceControl.release()方法释放SurfaceControl
SurfaceControl.release()
方法如下:
java
// frameworks/base/core/java/android/view/SurfaceControl.java
public void release() {
if (mNativeObject != 0) {
// 执行Runnable
mFreeNativeResources.run();
// 重置native SurfaceControl指针强转类型值
mNativeObject = 0;
// 重置native LayerHandler指针强转类型值
mNativeHandle = 0;
.....
mCloseGuard.close();
// mChoreographer置空
synchronized (mChoreographerLock) {
if (mChoreographer != null) {
mChoreographer.invalidate();
mChoreographer = null;
}
}
// 从SurfaceControlRegistry中移除,用于Debug
removeFromRegistry();
}
}
以上方法中:
- 执行
mFreeNativeResources.run()
,触发Native层对象内存的释放; - 将Native层对象句柄置为0;
mFreeNativeResources是一个Runnable类型对象,这是释放Native层资源的关键组件。mNativeObject和mNativeHandle分别是Native层SurfaceControl指针和LayerHandle指针地址。
1.2、NativeAllocationRegistry释放Native资源
我们知道,Java对象可以通过JVM垃圾回收器自动进行回收,但Native层对象必须显式进行释放才能回收,因此需要在JVM对象回收前,对引用的Native层资源也需要进行释放,这时就可以通过NativeAllocationRegistry来实现。
NativeAllocationRegistry用于对本地内存(Native Allocations)和Java对象进行关联,并将它们注册到运行时中。
在以上流程中,当执行release()
方法时,便通过mFreeNativeResources.run()
触发Native层对象资源的释放;
对于某个代码块内的SurfaceControl局部对象而言,会当Java对象由于GC释放内存时,Native层对象也将同步通过注册函数完成Native层内存的释放。
下面来看下NativeAllocationRegistry的具体使用。
1.2.1、获取NativeAllocationRegistry实例
在SurfaceControl创建过程中,会创建并获取一个NativeAllocationRegistry对象:
java
// frameworks/base/core/java/android/view/SurfaceControl.java
// 创建NativeAllocationRegistry实例
private static final NativeAllocationRegistry sRegistry =
NativeAllocationRegistry.createMalloced(SurfaceControl.class.getClassLoader(),
nativeGetNativeSurfaceControlFinalizer());
其中第二个参数是一个函数接口,用于释放Native层关联对象的函数。因此,当Java层SurfaceControl释放时,会执行nativeGetNativeSurfaceControlFinalizer()
方法对Native层对象进行释放。
1.2.2、关联Java Objects和Native Allocations
也是在SurfaceControl创建过程中,会通过NativeAllocationRegistry.registerNativeAllocation()
方法对Java层对象和Native层对象进行关联,并返回一个Runnable对象:
java
// frameworks/base/core/java/android/view/SurfaceControl.java
private void assignNativeObject(long nativeObject, String callsite) {
......
if (nativeObject != 0) {
// 注册待回收Native Allocation(nativeObject)对象并返回Runnable
mFreeNativeResources =
sRegistry.registerNativeAllocation(this, nativeObject);
}
.....
}
1.2.3、执行nativeGetNativeSurfaceControlFinalizer()释放Native资源
因此,在执行mFreeNativeResources.run()
后,将触发nativeGetNativeSurfaceControlFinalizer()
方法的执行:
cpp
// frameworks/base/core/jni/android_view_SurfaceControl.cpp
static jlong nativeGetNativeSurfaceControlFinalizer(JNIEnv* env, jclass clazz) {
return static_cast<jlong>(reinterpret_cast<uintptr_t>(&release));
}
static void release(SurfaceControl* ctrl) {
// 引用计数减1, 无引用后将析构
ctrl->decStrong((void *)nativeCreate);
}
当Native层sp指针引用计数为0后,将通过delete操作释放该指针,SurfaceControl将被析构。
1.3、执行SurfaceControl::~SurfaceControl()
Native层SurfaceControl析构方法如下:
cpp
// frameworks/native/libs/gui/SurfaceControl.cpp
SurfaceControl::~SurfaceControl()
{
// 清除sp<SurfaceComposerClient>引用计数
mClient.clear();
// 清除sp<LayerHandle>引用计数
mHandle.clear();
// 清除sp<BLASTBufferQueue>引用计数
mBbq.clear();
// 刷新Binder命令队列,同步服务端
IPCThreadState::self()->flushCommands();
}
以上方法中,对各类对象sp指针进行了引用计数清零,其中包括sp,之后surfaceflinger进程中将执行LayerHandler的析构。
在Binder IPC中,引用计数管理自动进行,不需要直接调用
IPCThreadState::processPendingDerefs()
方法。这个方法是 Binder IPC 机制内部的实现细节,由系统在适当的时机调用以确保资源正确管理。
此时,客户端进程SurfaceControl等对象内存完成释放。
二、LayerHandle销毁
进入surfaceflinger进程,LayerHandle析构方法如下:
cpp
// frameworks/native/services/surfaceflinger/FrontEnd/LayerHandle.cpp
LayerHandle::~LayerHandle() {
if (mFlinger) {
// 执行SurfaceFlinger::onHandleDestroyed()
mFlinger->onHandleDestroyed(this, mLayer, mLayerId);
}
}
以上方法中,直接执行SurfaceFlinger::onHandleDestroyed()方法。
2.1、SurfaceFlinger::onHandleDestroyed()
cpp
// frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::onHandleDestroyed(BBinder* handle, sp<Layer>& layer, uint32_t layerId) {
{
std::scoped_lock<std::mutex> lock(mCreatedLayersLock);
// 将LayerId添加到mDestroyedHandles列表中
mDestroyedHandles.emplace_back(layerId);
}
Mutex::Autolock lock(mStateLock);
// 将Layer对象添加到待移除列表中
markLayerPendingRemovalLocked(layer);
// 将mHandleAlive属性设置为false
layer->onHandleDestroyed();
mBufferCountTracker.remove(handle);
// 清除sp<Layer>引用计数
layer.clear();
// 设置eTransactionNeeded标记,发起surfaceflinger提交操作
setTransactionFlags(eTransactionFlushNeeded);
}
以上方法中:
-
将Layer ID添加到
mDestroyedHandles
列表中,mDestroyedHandles
列表中保存的是销毁LayerHandle对应的Layer ID,在收到VSYNC信号执行事务提交和更新时,会填充给frontend::Update。(这个列表在LifeCycleManager方案中使用,Android U版本没有使用); -
执行
markLayerPendingRemovalLocked()
将方法Layer对象添加到待移除列表中; -
执行
layer->onHandleDestroyed()
方法将mHandleAlive
属性设置为false,表示LayerHandle已经被销毁; -
清除LayerHandler中的sp引用计数,之后
LayerHandle::mLayer
将被置为nullptr,但由于其他位置依然存在对Layer的引用,因此此次clear不会触发Layer析构方法的执行; -
执行
setTransactionFlags()
方法触发SurfaceFlinger中VSYNC的调度。
2.1.1、加入mLayersPendingRemoval列表
markLayerPendingRemovalLocked()
方法中,将Layer添加到mLayersPendingRemoval
列表中:
cpp
// frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::markLayerPendingRemovalLocked(const sp<Layer>& layer) {
// 将Layer添加到mLayersPendingRemoval列表中
mLayersPendingRemoval.add(layer);
// 一个标记值,用于在合成过程遍历mLayersPendingRemoval列表
mLayersRemoved = true;
// 设置eTransactionNeeded标记
setTransactionFlags(eTransactionNeeded);
}
mLayersPendingRemoval中保存待销毁的Layer,在之后执行Layer更新时,将会从该列表中取出Layer,并执行相应的LayerTree移除操作。
LayerHandle析构执行完毕后,意味着LayerHandle完成销毁。接下来,在SurfaceFlinger中收到VSYNC信号进行事务提交和Layer状态更新时,会对mLayersPendingRemoval列表中的Layer进行更新和移除,同时在这个过程中,当Layer指针引用计数清零后,开始析构Layer。
三、Layer销毁
Layer的析构必须在surfaceflinger主线程进行,否则将直接中止程序的执行。因此,在SurfaceFlinger中收到VSYNC信号后,在主线程进行下一次提交和合成过程中,会对待释放的Layer进行析构,同时更新合成输出内容。
在这个过程中,正常情况下,Layer的析构发生在以下两个操作中的任意一处:
- 在LayerHandle发生析构后,如果该Layer在上一帧还处于可见状态,该Layer以及其已经释放LayerHandle的子Layer会在
SurfaceFligner::composite()
方法中清空mPreviouslyComposedLayers
列表后开始析构; - 在LayerHandle发生析构后,如果该Layer在上一帧前就不处于可见状态,且不存在Parent Layer,则该Layer会在
SurfaceFlinger::doCommitTransactions()
方法中清空mLayersPendingRemoval
列表后开始析构。
下面看下在commit和composite过程中跟Layer销毁相关的逻辑。
3.1、commit过程中更新赃区域和OffscreenLayer列表
commit过程中,经过commit() -> updateLayerSnapshotsLegacy() -> commitTransactions()调用,在commitTransactionsLocked()方法中会首先针对mLayersPendingRemoval
中的元素进行dirty区域更新:
cpp
// frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::commitTransactionsLocked(uint32_t transactionFlags) {
// Commit display transactions.
const bool displayTransactionNeeded = transactionFlags & eDisplayTransactionNeeded;
mFrontEndDisplayInfosChanged = displayTransactionNeeded;
....
// Layer销毁相关
if (mLayersRemoved) {
mLayersRemoved = false;
mVisibleRegionsDirty = true;
mUpdateInputInfo = true;
// 遍历mDrawingState.layersSortedByZ列表,更新脏区域
mDrawingState.traverseInZOrder([&](Layer* layer) {
if (mLayersPendingRemoval.indexOf(sp<Layer>::fromExisting(layer)) >= 0) {
Region visibleReg;
visibleReg.set(layer->getScreenBounds());
invalidateLayerStack(layer->getOutputFilter(), visibleReg);
}
});
}
......
doCommitTransactions();
}
以上方法代码片段中:
- 会将待移除Layer对应区域标记为"赃区域",在之后的合成阶段对赃区域进行处理;
- 执行doCommitTransactions()方法,更新
mCurrentState.layersSortedByZ
列表、OffScreenLayers列表等 ;
3.1.1、更新dirtyRegion
进入mLayersPendingRemoval列表的Layer,表示是待移除的Layer,Layer对应的区域也需要在合成时进行刷新,因此把这部分跟Layer面积相同的区域标记为赃区域,通过invalidateLayerStack()方法标记:
cpp
// frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::invalidateLayerStack(const ui::LayerFilter& layerFilter, const Region& dirty) {
// 遍历DisplayDevice列表
for (const auto& [token, displayDevice] : FTL_FAKE_GUARD(mStateLock, mDisplays)) {
auto display = displayDevice->getCompositionDisplay();
// 根据layerFilter找到对应的DisplayDevice,
// 并对对应OutputCompositionState.dirtyRegion进行区域标记
if (display->includesLayer(layerFilter)) {
display->editState().dirtyRegion.orSelf(dirty);
}
}
}
最终对CompostionDisplay的OutputCompositionState.dirtyRegion属性进行了更新,OutputCompositionState属性是合成过程中用于记录状态的属性,如屏幕的合成方式、内容投射区域、色彩空间、色彩矩阵等等.....
3.1.2、更新DrawingState和OffScreenLayers列表
接下来执行doCommitTransactions()
方法,开始更新SurfaceFlinger.mDrawingState
和OffScreenLayer列表:
cpp
// frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::doCommitTransactions() {
if (!mLayersPendingRemoval.isEmpty()) {
// Notify removed layers now that they can't be drawn from
for (const auto& l : mLayersPendingRemoval) {
// 释放Buffer
if (l->isRemovedFromCurrentState()) {
l->latchAndReleaseBuffer();
}
// 对于Root节点Layer, 从RootLayer列表中移除
if (l->isAtRoot()) {
l->setIsAtRoot(false);
mCurrentState.layersSortedByZ.remove(l);
}
// 对于不存在Parent的Layer,将其添加到mOffscreenLayers中
if (!l->getParent()) {
mOffscreenLayers.emplace(l.get());
}
}
// 清空mLayersPendingRemoval列表
mLayersPendingRemoval.clear();
}
// 更新mDrawingState
mDrawingState = mCurrentState;
// clear the "changed" flags in current state
mCurrentState.colorMatrixChanged = false;
// 更新Layer内部DrawingState
if (mVisibleRegionsDirty) {
for (const auto& rootLayer : mDrawingState.layersSortedByZ) {
rootLayer->commitChildList();
}
}
// 更新OffScreenLayer内部状态
commitOffscreenLayers();
......
}
以上方法中:
-
对于没有Parent的根节点Layer,会将其从根节点Layer列表
mCurrentState.layersSortedByZ
中直接移除; -
对于不存在Parent的Layer,会将其添加到
mOffscreenLayers
列表中; -
清空
mLayersPendingRemoval
列表; -
将mCurrentState更新给mDrawingState;
-
执行
commitOffscreenLayers()
更新OffScreenLayer状态。
以上逻辑执行完毕后,mLayersPendingRemoval
列表被清空,因此如果此时sp计数也恰好为0,就开始执行Layer析构方法。
OffscreenLayer表示不再参与合成但未析构的Layer。另外,需要注意的是,mOffscreenLayers列表中是直接将Layer*进行保存,其不会影响sp引用计数。
3.2、composite过程中更新mPreviouslyComposedLayers列表
mPreviouslyComposedLayers
列表中保存的是上一帧合成时参与合成的Layer。每次合成时,如果存在赃区域,会在moveSnapshotsToCompositionArgs()
方法中对其进行更新:
cpp
// frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
std::vector<std::pair<Layer*, LayerFE*>> SurfaceFlinger::moveSnapshotsToCompositionArgs(
compositionengine::CompositionRefreshArgs& refreshArgs, bool cursorOnly, int64_t vsyncId) {
std::vector<std::pair<Layer*, LayerFE*>> layers;
if (mLayerLifecycleManagerEnabled) {
......
}
if (mLegacyFrontEndEnabled && !mLayerLifecycleManagerEnabled) {
// 定义函数moveSnapshots,接收一个Layer指针类型参数
auto moveSnapshots = [&layers, &refreshArgs, cursorOnly](Layer* layer) {
if (const auto& layerFE = layer->getCompositionEngineLayerFE()) {
if (cursorOnly &&
layer->getLayerSnapshot()->compositionType !=
aidl::android::hardware::graphics::composer3::Composition::CURSOR)
return;
// 更新LayerSnapshot
layer->updateSnapshot(refreshArgs.updatingGeometryThisFrame);
// 将LayerSnapshot转移给LayerFE
layerFE->mSnapshot = layer->stealLayerSnapshot();
refreshArgs.layers.push_back(layerFE);
layers.emplace_back(layer, layerFE.get());
}
};
if (cursorOnly || !mVisibleRegionsDirty) {
......
} else {
// 清空mPreviouslyComposedLayers列表
mPreviouslyComposedLayers.clear();
// 遍历Layer列表
mDrawingState.traverseInZOrder(
[&moveSnapshots](Layer* layer) { moveSnapshots(layer); });
mPreviouslyComposedLayers.reserve(layers.size());
// 将参与合成的Layer重新添加到列表mPreviouslyComposedLayers
for (auto [layer, _] : layers) {
mPreviouslyComposedLayers.push_back(sp<Layer>::fromExisting(layer));
}
}
}
return layers;
}
以上方法中,会将该帧参与合成的Layer添加到列表mPreviouslyComposedLayers
,而不参与合成的将移除掉。
正常情况下,从mPreviouslyComposedLayers
中移除后,sp对象引用计数将清零,后续将开始执行Layer的析构。
3.2、执行Layer::~Layer()
Layer析构方法如下:
cpp
// frameworks/native/services/surfaceflinger/Layer.cpp
Layer::~Layer() {
// 必须在主线程执行
LOG_ALWAYS_FATAL_IF(std::this_thread::get_id() != mFlinger->mMainThreadId,
"Layer destructor called off the main thread.");
// 执行onReleaseBuffer方法回调,通知BBQ释放Buffer
if (mBufferInfo.mBuffer != nullptr) {
callReleaseBufferCallback(mDrawingState.releaseBufferListener,
mBufferInfo.mBuffer->getBuffer(), mBufferInfo.mFrameNumber,
mBufferInfo.mFence);
}
// 移除该Layer的Texture
// Clone Layer和Original Layer共享一个Texture
if (!isClone()) {
mFlinger->deleteTextureAsync(mTextureName);
}
......
// Layer销毁后的回调
mFlinger->onLayerDestroyed(this);
......
}
在以上方法中,分别对Layer相关资源也进行了释放,然后执行mFlinger->onLayerDestroyed()
方法:
cpp
// frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::onLayerDestroyed(Layer* layer) {
// Layer数 -1
mNumLayers--;
// 从offscreenLayer列表中移除
removeHierarchyFromOffscreenLayers(layer);
// 从调度器中移除Layer,用于刷新率管控
if (!layer->isRemovedFromCurrentState()) {
mScheduler->deregisterLayer(layer);
}
.......
}
以上方法中:
-
执行
removeHierarchyFromOffscreenLayers()
方法,将Layer从offscreenLayer列表中移除; -
执行mScheduler->deregisterLayer()方法,将Layer从Scheduler中移除,用于刷新率管控。
removeHierarchyFromOffscreenLayers()
方法移除OffscreenLayer如下:
cpp
// frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::removeHierarchyFromOffscreenLayers(Layer* layer) {
// 如果析构Layer存在子Layer, 则会将子Layer添加到offScreenLayer列表中
for (auto& child : layer->getCurrentChildren()) {
mOffscreenLayers.emplace(child.get());
}
// 从OffScreenLayer列表中移除
mOffscreenLayers.erase(layer);
}
因此,当Layer完成析构,便从OffscreenLayer列表中移除。
以上就是整个Layer的销毁过程。
下面对OffscreenLayer和Layer泄漏场景做下补充说明。
四、关于OffscreenLayer
OffscreenLayer表示从Layer树结构不可达(不再参与合成)但未析构的Layer。这里再说明下关于OffScreenLayer的三个问题:
-
OffscreenLayer的作用是什么?
-
什么情况下会将Layer添加到OffscreenLayer列表?
-
什么情况下会将Layer从OffscreenLayer列表中移除?
4.1、OffscreenLayer的作用
OffscreenLayer的特点是:不可达、不参与合成、Layer未析构、但依然可以接收GraphicBuffer的更新。
因此,当需要持续更新图层显示数据但又不希望图层显示时,可以将它作为"离屏图层"放入OffscreenLayer列表中,等再需要它显示时,重新从OffscreenLayer列表中移出来,继续参与合成过程。
如此一来,可以避免频繁地创建和销毁Layer对象,从而提高系统的性能和进行资源的复用。
4.2、添加到OffscreenLayer列表的场景
以下三种场景可以将Layer添加到offscreenLayer中:
-
当一个LayerHandle发生析构,且对应Layer没有Parent Layer时,会将对应Layer加入OffscreenLayer列表中(并在Layer析构时从Offscreen列表中移除);
-
当一个Layer发生析构后,会将其所有子Layer加入OffscreenLayer列表;
-
当一个Layer进行reparent,且将其Parent置为空时,会将该Layer加入OffscreenLayer列表;
前两种场景已在上面进行过说明,这里补充下第三种场景。第三种场景跟Layer的reparent操作有关,因此这里对reparent过程做个完成的说明。
4.2.1、Layer的reparent过程
从Layer::reparent()
方法看起:
cpp
// frameworks/native/services/surfaceflinger/Layer.cpp
bool Layer::reparent(const sp<IBinder>& newParentHandle) {
......
sp<Layer> parent = getParent();
// 当前Parent Layer中移除该Layer
if (parent != nullptr) {
parent->removeChild(sp<Layer>::fromExisting(this));
}
if (newParentHandle != nullptr) {
// 如果新Parent Layer不为空,添加到新Parent Layer中
newParent->addChild(sp<Layer>::fromExisting(this));
// 如果新Parent Layer参与合成过程,则该Layer也将参与到合成过程
// 否则,将该Layer添加到待移除列表中
if (!newParent->isRemovedFromCurrentState()) {
addToCurrentState();
} else {
onRemovedFromCurrentState();
}
} else {
// 否则,将该Layer添加到待移除列表中
onRemovedFromCurrentState();
}
return true;
}
以上方法中:
-
如果新Parent Layer不为空,则将该Layer添加到新Parent Layer的Child列表中;
- 如果新Parent Layer参与合成过程,则该Layer也将参与;
- 如果新Parent Layer不参与合成过程,则将该Layer及它的子Layer添加到待移除列表中;
-
如果新Parent Layer为空,则将该LayerLayer及它的子Layer添加到待移除列表中,并在随后添加到OffscreenLayer中;
Layer::mRemovedFromDrawingState
属性表示该Layer是否参与合成过程,默认为false,当不需要参与合成过程时,会通过Layer::onRemovedFromCurrentState()
方法将该Layer及它的子Layer的该属性值设置为true,随后加入到mLayersPendingRemoval列表中:
cpp
// frameworks/native/services/surfaceflinger/Layer.cpp
void Layer::onRemovedFromCurrentState() {
// 获取当前Layer所在的整个LayerTree
auto layersInTree = getRootLayer()->getLayersInTree(LayerVector::StateSet::Current);
std::sort(layersInTree.begin(), layersInTree.end());
REQUIRE_MUTEX(mFlinger->mStateLock);
// 遍历当前Layer的子Layer,并执行自身及子Layer的removeFromCurrentState()方法
traverse(LayerVector::StateSet::Current,
[&](Layer* layer) REQUIRES(layer->mFlinger->mStateLock) {
layer->removeFromCurrentState();
layer->removeRelativeZ(layersInTree);
});
}
最终调用Layer::removeFromCurrentState()
方法,更新了mRemovedFromDrawingState
值,并添加到了mLayersPendingRemoval
中:
cpp
// frameworks/native/services/surfaceflinger/Layer.cpp
void Layer::removeFromCurrentState() {
// 将mRemovedFromDrawingState值修改为true
if (!mRemovedFromDrawingState) {
mRemovedFromDrawingState = true;
mFlinger->mScheduler->deregisterLayer(this);
}
updateTrustedPresentationState(nullptr, nullptr, -1 /* time_in_ms */, true /* leaveState*/);
// 添加到待移除列表中
mFlinger->markLayerPendingRemovalLocked(sp<Layer>::fromExisting(this));
}
之后,便根据3.1.2小节中的内容,将mLayersPendingRemoval
中不存在Parent Layer的Layer添加到mOffscreenLayers
中。
4.3、移出OffscreenLayer列表的场景
以下两种场景下,会将Layer从OffscreenLayer列表中移除:
- 当一个Layer发生析构后,会将其从OffscreenLayer列表中移除,这时该Layer已经彻底销毁,见
SurfaceFlinger::onLayerDestroyed()
方法; - 当一个Layer进行reparent,对其设置一个参与合成过程的Parent Layer时,会将其从OffscreenLayer列表中移除,这时该Layer及其子Layer将重新参与合成过程。
第二种场景在Layer::addToCurrentState()
方法中:
cpp
// frameworks/native/services/surfaceflinger/Layer.cpp
void Layer::addToCurrentState() {
if (mRemovedFromDrawingState) {
mRemovedFromDrawingState = false;
// 向调度器注册Layer
mFlinger->mScheduler->registerLayer(this);
// 从Offscreen中移除
mFlinger->removeFromOffscreenLayers(this);
}
// 对子Layer进行同样操作
for (const auto& child : mCurrentChildren) {
child->addToCurrentState();
}
}
void SurfaceFlinger::removeFromOffscreenLayers(Layer* layer) {
mOffscreenLayers.erase(layer);
}
如果一直位于OffsreenLayer中且一直没有进行移除,则可能发生了OffscreenLayer泄漏。
五、Layer泄漏场景
通过对Layer创建和销毁流程的分析,可以看到SurfaceControl、LayerHandle、Layer三者关联性非常强,任意一个出现问题,都可能导致Layer发生泄漏,进而影响整个系统。
导致Layer泄漏的常见原因主要有:
-
SurfaceControl操作不合理。
- 业务侧在使用完毕SurfaceControl后,没有执行
SurfaceControl.release()
进行释放; - 业务侧在释放时,如果存在父SurfaceControl,没有执行
SurfaceControl.reparent(null)
; - 业务侧创建了多份SurfaceControl副本,且没有对所有副本都执行以上操作。
- 业务侧在使用完毕SurfaceControl后,没有执行
-
LayerHandle操作不合理。
- SurfaceControl未析构,持有LayerHandle引用;
- ComposerState未析构,持有LayerHandle引用。
-
Layer操作不合理。
- 释放时没有将Parent Layer置空;
- 仅对Parent Layer进行释放,未释放子Layer;
因此,在使用SurfaceControl时,需要规范使用。当出现Layer泄漏问题时,也可以从这几个方向出发排查具体原因。