SurfaceFlinger07-Layer销毁流程

前言

在上一篇文章中,对Layer的创建流程进行了分析。Layer创建完成后,根节点或Parent Layer是保存在SurfaceFlinger类中的mCurrentState.layersSortedByZmDrawingState.layersSortedByZ列表中,而子Layer则是保存在对应Parent Layer的mCurrentChildrenmDrawingChildren列表中。

同时,在客户端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销毁有两种方式:

  1. 调用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();

  1. 调用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();
        }
    }

以上方法中:

  1. 执行mFreeNativeResources.run(),触发Native层对象内存的释放;
  2. 将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);
}

以上方法中:

  1. 将Layer ID添加到mDestroyedHandles列表中,mDestroyedHandles列表中保存的是销毁LayerHandle对应的Layer ID,在收到VSYNC信号执行事务提交和更新时,会填充给frontend::Update。(这个列表在LifeCycleManager方案中使用,Android U版本没有使用);

  2. 执行markLayerPendingRemovalLocked()将方法Layer对象添加到待移除列表中;

  3. 执行layer->onHandleDestroyed()方法将mHandleAlive属性设置为false,表示LayerHandle已经被销毁;

  4. 清除LayerHandler中的sp引用计数,之后LayerHandle::mLayer将被置为nullptr,但由于其他位置依然存在对Layer的引用,因此此次clear不会触发Layer析构方法的执行;

  5. 执行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的析构发生在以下两个操作中的任意一处:

  1. 在LayerHandle发生析构后,如果该Layer在上一帧还处于可见状态,该Layer以及其已经释放LayerHandle的子Layer会在SurfaceFligner::composite()方法中清空mPreviouslyComposedLayers列表后开始析构;
  2. 在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();
}

以上方法代码片段中:

  1. 会将待移除Layer对应区域标记为"赃区域",在之后的合成阶段对赃区域进行处理;
  2. 执行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();
    ......
}

以上方法中:

  1. 对于没有Parent的根节点Layer,会将其从根节点Layer列表mCurrentState.layersSortedByZ中直接移除;

  2. 对于不存在Parent的Layer,会将其添加到mOffscreenLayers列表中;

  3. 清空mLayersPendingRemoval列表;

  4. 将mCurrentState更新给mDrawingState;

  5. 执行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);
    }
    .......
}

以上方法中:

  1. 执行removeHierarchyFromOffscreenLayers()方法,将Layer从offscreenLayer列表中移除;

  2. 执行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的三个问题:

  1. OffscreenLayer的作用是什么?

  2. 什么情况下会将Layer添加到OffscreenLayer列表?

  3. 什么情况下会将Layer从OffscreenLayer列表中移除?

4.1、OffscreenLayer的作用

OffscreenLayer的特点是:不可达、不参与合成、Layer未析构、但依然可以接收GraphicBuffer的更新。

因此,当需要持续更新图层显示数据但又不希望图层显示时,可以将它作为"离屏图层"放入OffscreenLayer列表中,等再需要它显示时,重新从OffscreenLayer列表中移出来,继续参与合成过程。

如此一来,可以避免频繁地创建和销毁Layer对象,从而提高系统的性能和进行资源的复用。

4.2、添加到OffscreenLayer列表的场景

以下三种场景可以将Layer添加到offscreenLayer中:

  1. 当一个LayerHandle发生析构,且对应Layer没有Parent Layer时,会将对应Layer加入OffscreenLayer列表中(并在Layer析构时从Offscreen列表中移除);

  2. 当一个Layer发生析构后,会将其所有子Layer加入OffscreenLayer列表;

  3. 当一个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;
}

以上方法中:

  1. 如果新Parent Layer不为空,则将该Layer添加到新Parent Layer的Child列表中;

    • 如果新Parent Layer参与合成过程,则该Layer也将参与;
    • 如果新Parent Layer不参与合成过程,则将该Layer及它的子Layer添加到待移除列表中;
  2. 如果新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列表中移除:

  1. 当一个Layer发生析构后,会将其从OffscreenLayer列表中移除,这时该Layer已经彻底销毁,见SurfaceFlinger::onLayerDestroyed()方法;
  2. 当一个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泄漏的常见原因主要有:

  1. SurfaceControl操作不合理。

    • 业务侧在使用完毕SurfaceControl后,没有执行SurfaceControl.release()进行释放;
    • 业务侧在释放时,如果存在父SurfaceControl,没有执行SurfaceControl.reparent(null)
    • 业务侧创建了多份SurfaceControl副本,且没有对所有副本都执行以上操作。
  2. LayerHandle操作不合理。

    • SurfaceControl未析构,持有LayerHandle引用;
    • ComposerState未析构,持有LayerHandle引用。
  3. Layer操作不合理。

    • 释放时没有将Parent Layer置空;
    • 仅对Parent Layer进行释放,未释放子Layer;

因此,在使用SurfaceControl时,需要规范使用。当出现Layer泄漏问题时,也可以从这几个方向出发排查具体原因。

相关推荐
百锦再43 分钟前
Android Studio开发 SharedPreferences 详解
android·ide·android studio
青春给了狗1 小时前
Android 14 修改侧滑手势动画效果
android
CYRUS STUDIO1 小时前
Android APP 热修复原理
android·app·frida·hotfix·热修复
火柴就是我2 小时前
首次使用Android Studio时,http proxy,gradle问题解决
android
limingade2 小时前
手机打电话时电脑坐席同时收听对方说话并插入IVR预录声音片段
android·智能手机·电脑·蓝牙电话·电脑打电话
浩浩测试一下2 小时前
计算机网络中的DHCP是什么呀? 详情解答
android·网络·计算机网络·安全·web安全·网络安全·安全架构
青春给了狗4 小时前
Android 14 系统统一修改app启动时图标大小和圆角
android
pengyu5 小时前
【Flutter 状态管理 - 柒】 | InheritedWidget:藏在组件树里的"魔法"✨
android·flutter·dart
居然是阿宋6 小时前
Kotlin高阶函数 vs Lambda表达式:关键区别与协作关系
android·开发语言·kotlin
凉、介6 小时前
PCI 总线学习笔记(五)
android·linux·笔记·学习·pcie·pci