SurfaceFlinger中有Layer泄漏一直增长超过4096问题如何排查-实战问题分析排查

Andorid Surface(3.3) android Surface(3.3) 阅读详情
AI摘要

本文详细分析了SurfaceFlinger中Layer泄漏导致数量超过4096的问题。首先介绍了Layer的创建与销毁流程,包括Java层和native层的交互。然后通过实际案例,探讨了Layer泄漏的原因和排查方法,最终提出了解决方案。

背景:

有学员在vip群里反馈一个SurfaceFlinger相关的报错
在这里插入图片描述
群里讨论也非常激烈。
问题如下:
在这里插入图片描述sf的报错信息大概可以看出这个是创建的Layer数量已经大于4096个,sf端有保护机制,为了让内存不会永久持续增大,只能报错异常,不然在创建新的。

对应的代码如下:
frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
在这里插入图片描述
那么出现这种问题一般是什么原因呢?正常的系统要展示窗口时候创建layer,不展示时候肯定就会销毁layer,这样layer肯定不会只增不减,所以4096在长期经验来说已经足够大了,一旦会超过4096这个数量,那一般就是有泄露。

那么这种问题如何排查呢?这个相关优秀学员也回答很详细,在这里给大家做一个记录,方便大家以后遇到同样问题可以参考这篇文章。
在这里插入图片描述在这里插入图片描述

【Android 13】SurfaceFlinger - Layer的创建与销毁

SurfaceControl的创建

SurfaceControl的创建流程(app端创建SurfaceControl,sf端创建Layer)
在这里插入图片描述

Java层

ViewRootImpl创建SurfaceSession和SurfaceControl

ViewRootImpl的SurfaceSession在初始化的时候就构造完成:

代码位于:frameworks/base/core/java/android/view/ViewRootImpl.java
private final SurfaceSession mSurfaceSession = new SurfaceSession();
代码位于:frameworks/base/core/java/android/view/SurfaceSession.java
public SurfaceSession() {
    mNativeClient = nativeCreate();
}

ViewRootImpl通过setView()可以通过Session在system_server端构建一个WindowToken和WindowState。WindowToken和WindowState这类窗口容器的SurfaceControl在1.1.2中提到创建过程。

ViewRootImpl在初始化的时候,就构造了一个空的SurfaceControl:

代码位于frameworks/base/core/java/android/view/ViewRootImpl.java

private final SurfaceControl mSurfaceControl = new SurfaceControl();

在ViewRootImpl需要绘制的时候,通过session.relayout()会在system_server端为这个ViewRootImpl创建一个SurfaceControl,挂到WindowState下面去:

代码位于frameworks/base/core/java/android/view/ViewRootImpl.java

 private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,
            boolean insetsPending) throws RemoteException {
            //...
    relayoutResult = mWindowSession.relayout(mWindow, params,
                    requestedWidth, requestedHeight, viewVisibility,
                    insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0,
                    mTmpFrames, mPendingMergedConfiguration, mSurfaceControl /* 注意到这里把SurfaceControl作参数传入 */, mTempInsets,
                    mTempControls, mRelayoutBundle);
}

来到WMS,在relayout的过程中会为其构建真正的SurfaceControl (implements Parcelable),并将创建好的SurfaceControl回传给应用端的ViewRootImpl:

代码位于frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java

public int relayoutWindow(Session session, IWindow client, LayoutParams attrs,
            int requestedWidth, int requestedHeight, int viewVisibility, int flags,
            ClientWindowFrames outFrames, MergedConfiguration mergedConfiguration,
            SurfaceControl outSurfaceControl, InsetsState outInsetsState,
            InsetsSourceControl[] outActiveControls, Bundle outSyncIdBundle) {
    // ...
    // Create surfaceControl before surface placement otherwise layout will be skipped
    // (because WS.isGoneForLayout() is true when there is no surface.
    if (shouldRelayout) {
        try {
            result = createSurfaceControl(outSurfaceControl, result, win, winAnimator);
        } catch (Exception e) {
            displayContent.getInputMonitor().updateInputWindowsLw(true /*force*/);
            Binder.restoreCallingIdentity(origId);
            return 0;
        }
    }   
}

private int createSurfaceControl(SurfaceControl outSurfaceControl, int result,
        WindowState win, WindowStateAnimator winAnimator) {
    WindowSurfaceController surfaceController;
    // 在system_server端为ViewRootImpl构建一个SurfaceControl
    // winAnimator是WindowState的一个成员变量,这个WindowState是ViewRootImpl在system_server侧的挂载父亲
    surfaceController = winAnimator.createSurfaceLocked();
    if (surfaceController != null) {
        // 将创建好的SurfaceControl回传给ViewRootImpl
        surfaceController.getSurfaceControl(outSurfaceControl);
    } else {
        ProtoLog.w(WM_ERROR, "Failed to create surface control for %s", win);
        outSurfaceControl.release();
    }
    return result;
}

WindowStateAnimator中会构建一个mSurfaceController,其中维护了mSurfaceControl:

代码位于frameworks/base/services/core/java/com/android/server/wm/WindowStateAnimator.java

WindowSurfaceController createSurfaceLocked() {
    final WindowState w = mWin;
    if (mSurfaceController != null) {
        return mSurfaceController;
    }
    // ...
    mSurfaceController = new WindowSurfaceController(attrs.getTitle().toString(), format,
        flags, this, attrs.type);
    // ...
    return mSurfaceController;
}

实例化WindowSurfaceController的时候,构造了mSurfaceControl,可以通过其getSurfaceControl()方法,将其拷贝出去:

  • 需要注意的是,这里为ViewRootImpl创建的SurfaceControl的父亲,就是其需要挂载的WindowState的SurfaceControl

代码位于frameworks/base/services/core/java/com/android/server/wm/WindowSurfaceController.java

WindowSurfaceController(String name, int format, int flags, WindowStateAnimator animator,
            int windowType) {
    mAnimator = animator;

    title = name;

    mService = animator.mService;
    final WindowState win = animator.mWin;
    mWindowType = windowType;
    mWindowSession = win.mSession;

    Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "new SurfaceControl");
    final SurfaceControl.Builder b = win.makeSurface()
            .setParent(win.getSurfaceControl()) /* 需要注意的是,ViewRootImpl创建的SurfaceControl挂载的父亲就是WindowState */
            .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();

    Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}

WindowContainer创建SurfaceSession和SurfaceControl

WindowContainer的SurfaceSession在DisplayContent初始化的时候就构造完成,其孩子使用session时,可以从父亲这里取得Session:

代码位于:frameworks/base/services/core/java/com/android/server/wm/DisplayContent.java

 private final SurfaceSession mSession = new SurfaceSession();

当WindowContainer挂载到窗口结构树上时,会为其初始化一个SurfaceControl与该窗口容器一一对应:

代码位于frameworks/base/services/core/java/com/android/server/wm/WindowContainer.java

void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent,
            PreAssignChildLayersCallback callback) {
    //...
    if (mSurfaceControl == null) {
        createSurfaceControl(false /*force*/);
    } else {
        reparentSurfaceControl(getSyncTransaction(), mParent.mSurfaceControl);
    }
}

使用SurfaceControl.Builder进行构造:

代码位于frameworks/base/services/core/java/com/android/server/wm/WindowContainer.java

void createSurfaceControl(boolean force) {
    setInitialSurfaceControlProperties(makeSurface());
}

SurfaceControl.Builder makeSurface() {
    final WindowContainer p = getParent();
    return p.makeChildSurface(this);
}

void setInitialSurfaceControlProperties(SurfaceControl.Builder b) {
    setSurfaceControl(b.setCallsite("WindowContainer.setInitialSurfaceControlProperties").build());
    if (showSurfaceOnCreation()) {
        getSyncTransaction().show(mSurfaceControl);
    }
    onSurfaceShown(getSyncTransaction());
    updateSurfacePositionNonOrganized();
}

如果窗口容器是Task.java,还会为SurfaceControl打上EffectLayer标签

代码位于frameworks/base/services/core/java/com/android/server/wm/Task.java

@Override
void setInitialSurfaceControlProperties(SurfaceControl.Builder b) {
    b.setEffectLayer().setMetadata(METADATA_TASK_ID, mTaskId);
    super.setInitialSurfaceControlProperties(b);
}

jni的发起

最终都会通过SurfaceController.Build()的方式,进行SurfaceControl的构造。SurfaceControl.java只是一个壳,真正的对象在native层:

代码位于frameworks/base/core/java/android/view/SurfaceControl.java

 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 {
    if (name == null) {
        throw new IllegalArgumentException("name must not be null");
    }

    mName = name;
    mWidth = w;
    mHeight = h;
    mLocalOwnerView = localOwnerView;
    Parcel metaParcel = Parcel.obtain();
    try {
        if (metadata != null && metadata.size() > 0) {
            metaParcel.writeInt(metadata.size());
            for (int i = 0; i < metadata.size(); ++i) {
                metaParcel.writeInt(metadata.keyAt(i));
                metaParcel.writeByteArray(
                        ByteBuffer.allocate(4).order(ByteOrder.nativeOrder())
                                .putInt(metadata.valueAt(i)).array());
            }
            metaParcel.setDataPosition(0);
        }
        // 发起构建
        mNativeObject = nativeCreate(session, name, w, h, format, flags,
                parent != null ? parent.mNativeObject : 0, metaParcel);
    } finally {
        metaParcel.recycle();
    }
    if (mNativeObject == 0) {
        throw new OutOfResourcesException(
                "Couldn't allocate SurfaceControl native object");
    }
    mNativeHandle = nativeGetHandle(mNativeObject);
    mCloseGuard.openWithCallSite("release", callsite);
}

private static native long nativeCreate(SurfaceSession session, String name,
        int w, int h, int format, int flags, long parentObject, Parcel metadata)
        throws OutOfResourcesException;

native层

代码位于:frameworks/base/core/jni/android_view_SurfaceControl.cpp

  1. 获取一个SurfaceComposerClient的引用

    1. 这是客户端对象,将用于和SurfaceFlinger服务端通信
  2. sp parentHandle 指向传入的需要挂载的SurfaceControl父亲

    1. 在native层,通过handle来指向SurfaceControl,在SurfaceFlinger端,handle->owner指向Layer
  3. 通过SurfaceComposerClient创建SurfaceControl,同时将向sf发起构建Layer的请求

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;
    if (sessionObj != NULL) {
        client = android_view_SurfaceSession_getClient(env, sessionObj);
    } else {
        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();
    }

    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());
}

SurfaceComposerClient发起Layer(surfaceflinger服务端)和SurfaceControl(client端)构建:

  • 可以看到SurfaceControl对象也是存在于客户端的,其中维护了handle,这可以用来指向sf端的Layer
  • 这里的mClient则是位于sf端的Client.cpp对象的BpBinder,它的构建在下一小节解释

代码位于:frameworks/native/libs/gui/SurfaceComposerClient.cpp

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;
        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;
}

实例化SurfaceControl

将sf端构造好的Layer的句柄handle (BpBinder)进行维护,以便后续deconstructor()调用时,可以远程调用进行资源释放

代码位于:frameworks/native/libs/gui/SurfaceControl.cpp

SurfaceControl::SurfaceControl(const sp<SurfaceComposerClient>& client, const sp<IBinder>& handle,
                               const sp<IGraphicBufferProducer>& gbp, int32_t layerId,
                               uint32_t w, uint32_t h, PixelFormat format, uint32_t transform,
                               uint32_t flags)
      : mClient(client),
        mHandle(handle),
        mGraphicBufferProducer(gbp),
        mLayerId(layerId),
        mTransformHint(transform),
        mWidth(w),
        mHeight(h),
        mFormat(format),
        mCreateFlags(flags) {}

SurfaceComposerClient与SurfaceFlinger建联

SurfaceComposerClient获取SurfaceFlinger服务远程代理对象

当SurfaceComposerClient首次构建的时候,会尝试与SurfaceFlinger进程建立联系:

代码位于:frameworks/native/libs/gui/SurfaceComposerClient.cpp

代码位于:frameworks/native/libs/gui/SurfaceComposerClient.cpp

void SurfaceComposerClient::onFirstRef() {
    sp<ISurfaceComposer> sf(ComposerService::getComposerService());
    if (sf != nullptr && mStatus == NO_INIT) {
        sp<ISurfaceComposerClient> conn;
        conn = sf->createConnection();
        if (conn != nullptr) {
            mClient = conn;
            mStatus = NO_ERROR;
        }
    }
}

这里会获取一个sf对象,这是sf服务在客户端的BpBinder,通过ComposerService::getComposerService()获取:

代码位于:frameworks/native/libs/gui/SurfaceComposerClient.cpp

/*static*/ sp<ISurfaceComposer> ComposerService::getComposerService() {
    // ComposerService继承了Singleton这是个单例
    ComposerService& instance = ComposerService::getInstance();
    Mutex::Autolock _l(instance.mLock);
    if (instance.mComposerService == nullptr) {
        if (ComposerService::getInstance().connectLocked()) {
            ALOGD("ComposerService reconnected");
            WindowInfosListenerReporter::getInstance()->reconnect(instance.mComposerService);
        }
    }
    return instance.mComposerService;
}

在构造ComposerService的时候,通过ServiceManager获取SurfaceFlinger服务的BpBinder

代码位于:frameworks/native/libs/gui/SurfaceComposerClient.cpp

ComposerService::ComposerService()
: Singleton<ComposerService>() {
    Mutex::Autolock _l(mLock);
    connectLocked();
}

bool ComposerService::connectLocked() {
    const String16 name("SurfaceFlinger");
    mComposerService = waitForService<ISurfaceComposer>(name);
    if (mComposerService == nullptr) {
        return false; // fatal error or permission problem
    }

    // Create the death listener.
    class DeathObserver : public IBinder::DeathRecipient {
        ComposerService& mComposerService;
        virtual void binderDied(const wp<IBinder>& who) {
            ALOGW("ComposerService remote (surfaceflinger) died [%p]",
                  who.unsafe_get());
            mComposerService.composerServiceDied();
        }
     public:
        explicit DeathObserver(ComposerService& mgr) : mComposerService(mgr) { }
    };

    mDeathObserver = new DeathObserver(*const_cast<ComposerService*>(this));
    IInterface::asBinder(mComposerService)->linkToDeath(mDeathObserver);
    return true;
}

SurfaceComposerClient通过sf的BpBinder远程调用,创建Client的BpBinder,用于后续通信

回到SurfaceComposerClient构建的时机,获取到sf的BpBinder后,调用了其createConnection()方法,这会在SurfaceFlinger服务端构建一个Client.cpp的实体对象,它的BpBinder交给客户端,后续SurfaceComposerClient向sf服务发起请求,都通过client的BpBinder,而不总通过SurfaceFlinger的BpBinder

代码位于:frameworks/native/libs/gui/SurfaceComposerClient.cpp

void SurfaceComposerClient::onFirstRef() {
    sp<ISurfaceComposer> sf(ComposerService::getComposerService());
    if (sf != nullptr && mStatus == NO_INIT) {
        sp<ISurfaceComposerClient> conn;
        conn = sf->createConnection();
        if (conn != nullptr) {
            // 获取到Client的BpBinder
            mClient = conn;
            mStatus = NO_ERROR;
        }
    }
}

来到surfaceflinger进程,SurfaceFlinger.cpp响应createConnection()远程调用,构造一个Client,并将其BpBinder交给客户端:

代码位于:frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp

sp<ISurfaceComposerClient> SurfaceFlinger::createConnection() {
    const sp<Client> client = new Client(this);
    return client->initCheck() == NO_ERROR ? client : nullptr;
}

SurfaceComposerClient通过Client发起Layer创建

SurfaceControl与Layer的对应关系:

回到SurfaceComposerClient创建SurfaceControl,在客户端创建SurfaceControl之前,会通过Client的BpBinder在sf端建立Layer,并将其引用句柄handle回传,由即将创建的SurfaceControl维护:

代码位于:frameworks/native/libs/gui/SurfaceComposerClient.cpp

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) {
    // ...
    if (mStatus == NO_ERROR) {
        sp<IBinder> handle;
        err = mClient->createSurface(name, w, h, format, flags, parentHandle, std::move(metadata),
                                     &handle, &gbp, &id, &transformHint);
        if (err == NO_ERROR) {
            *outSurface =
                    new SurfaceControl(this, handle, gbp, id, w, h, format, transformHint, flags);
        }
    }
    return err;
}

来到surfaceflinger进程,Client.cpp响应该远程调用:

代码位于: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<IBinder>& parentHandle, LayerMetadata metadata,
                               sp<IBinder>* outHandle, sp<IGraphicBufferProducer>* /* gbp */,
                               int32_t* outLayerId, uint32_t* outTransformHint) {
    // We rely on createLayer to check permissions.
    LayerCreationArgs args(mFlinger.get(), this, name.c_str(), flags, std::move(metadata));
    return mFlinger->createLayer(args, outHandle, parentHandle, outLayerId, nullptr,
                                 outTransformHint);
}

转发给SurfaceFlinger.cpp来进行Layer的创建:

  • 根据不同的Layer类型进行创建,类型有:EffectLayer(例如Task的Layer),ContainerLayer(例如ActivityRecord的Layer), BufferStateLayer(有实在内容的Layer)
  • 将构建好的Layer进行记录,addClientLayer()
  • 为Layer带上sequence,这是递增的数值,用来维护其唯一性

代码位于:frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp

status_t SurfaceFlinger::createLayer(LayerCreationArgs& args, sp<IBinder>* outHandle,
                                     const sp<IBinder>& parentHandle, int32_t* outLayerId,
                                     const sp<Layer>& parentLayer, uint32_t* outTransformHint) {
    status_t result = NO_ERROR;
    sp<Layer> layer;
    switch (args.flags & ISurfaceComposerClient::eFXSurfaceMask) {
        case ISurfaceComposerClient::eFXSurfaceBufferQueue:
        case ISurfaceComposerClient::eFXSurfaceBufferState: {
            result = createBufferStateLayer(args, outHandle, &layer);
        } break;
        case ISurfaceComposerClient::eFXSurfaceEffect:
            result = createEffectLayer(args, outHandle, &layer);
            break;
        case ISurfaceComposerClient::eFXSurfaceContainer:
            result = createContainerLayer(args, outHandle, &layer);
            break;
        default:
            result = BAD_VALUE;
            break;
    }
    //...
    result = addClientLayer(args.client, *outHandle, layer, parent, addToRoot, outTransformHint);
    *outLayerId = layer->sequence;
    return result;
}

重点关注1: 构造Layer的时候,会同时构建一个指向该Layer的Handle, 以createEffectLayer为例:

代码位于frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp

status_t SurfaceFlinger::createEffectLayer(const LayerCreationArgs& args, sp<IBinder>* handle,
                                           sp<Layer>* outLayer) {
    *outLayer = getFactory().createEffectLayer(args);
    *handle = (*outLayer)->getHandle();
    return NO_ERROR;
}

代码位于:frameworks/native/services/surfaceflinger/Layer.cpp

sp<IBinder> Layer::getHandle() {
    Mutex::Autolock _l(mLock);
    if (mGetHandleCalled) {
        ALOGE("Get handle called twice" );
        return nullptr;
    }
    mGetHandleCalled = true;
    return new Handle(mFlinger, this);
}

重点关注到Handle:

  • 作为Layer的句柄,是BBinder类型,在sf端,可以通过owner找到对应的Layer,在客户端可以通过handle远程对应到Layer
  • 可以控制Layer的销毁,当Layer被销毁的时候,句柄也会销毁,会走到mFlinger->onHandleDestroyed(),从相关集合中移除,如mOffscreenLayers集合
/*
 * Trivial class, used to ensure that mFlinger->onLayerDestroyed(mLayer)
 * is called.
 */
class LayerCleaner {
    sp<SurfaceFlinger> mFlinger;
    sp<Layer> mLayer;
    BBinder* mHandle;

protected:
    ~LayerCleaner() {
        // destroy client resources
        mFlinger->onHandleDestroyed(mHandle, mLayer);
    }

public:
    LayerCleaner(const sp<SurfaceFlinger>& flinger, const sp<Layer>& layer, BBinder* handle)
          : mFlinger(flinger), mLayer(layer), mHandle(handle) {}
};

/*
 * The layer handle is just a BBinder object passed to the client
 * (remote process) -- we don't keep any reference on our side such that
 * the dtor is called when the remote side let go of its reference.
 *
 * LayerCleaner ensures that mFlinger->onLayerDestroyed() is called for
 * this layer when the handle is destroyed.
 */
class Handle : public BBinder, public LayerCleaner {
public:
    Handle(const sp<SurfaceFlinger>& flinger, const sp<Layer>& layer)
          : LayerCleaner(flinger, layer, this), owner(layer) {}
    const String16& getInterfaceDescriptor() const override { return kDescriptor; }

    static const String16 kDescriptor;
    wp<Layer> owner;
};

**重点关注2:**addClientLayer(),将创建好的Layer进行添加:

  • 记录到mCreatedLayers集合中
  • 将其与Client绑定

代码位于:frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp

status_t SurfaceFlinger::addClientLayer(const sp<Client>& client, const sp<IBinder>& handle,
                                        const sp<Layer>& layer, const wp<Layer>& parent,
                                        bool addToRoot, uint32_t* outTransformHint) {
    if (mNumLayers >= ISurfaceComposer::MAX_LAYERS /* 4096 */) {
        // 报错
        return NO_MEMORY;
    }
    
    {
        std::scoped_lock<std::mutex> lock(mCreatedLayersLock);
        mCreatedLayers.emplace_back(layer, parent, addToRoot);
    }
    
    // attach this layer to the client
    if (client != nullptr) {
        client->attachLayer(handle, layer);
    }
}

Client.cpp中维护Layer

  • 关系是, 一个SurfaceComposerClient持有一个Client的BpBinder,一个Client下可能维护有多个Layer,场景是 client->mirrorSurface() \ 再次client->createSurface()

SurfaceControl的销毁与Layer的释放

SurfaceControl的销毁

java层销毁SurfaceControl

java层,通过SurfaceControl.Transaction的remove()方法,可以进行SurfaceControl的销毁:

  • reparent到父亲为null
  • release释放引用关系

这使得Layer成为游离态,将会在sf端的mOffscreenLayers集合中存在,并在Layer所有引用消失的时候,调用析构函数,从mOffscreenLayers中移除,真正销毁Layer。

代码位于:frameworks/base/core/java/android/view/SurfaceControl.java

// SurfaceControl.Transaction
public Transaction remove(@NonNull SurfaceControl sc) {
    reparent(sc, null);
    sc.release();
    return this;
}

public Transaction reparent(@NonNull SurfaceControl sc,
        @Nullable SurfaceControl newParent) {
    checkPreconditions(sc);
    long otherObject = 0;
    if (newParent != null) {
        newParent.checkNotReleased();
        otherObject = newParent.mNativeObject;
    }
    nativeReparent(mNativeObject, sc.mNativeObject, otherObject);
    mReparentedSurfaces.put(sc, newParent);
    return this;
}
// SurfaceControl
public void release() {
    if(LOG_SURFACE_CONTROL) {
        Log.d(TAG, "release, mNativeObject:" + mNativeObject, new Throwable());
    }

    if (mNativeObject != 0) {
        nativeRelease(mNativeObject);
        mNativeObject = 0;
        mNativeHandle = 0;
        mCloseGuard.close();
    }
}

native层销毁SurfaceControl

SurfaceControl.cpp继承于RefBase.cpp,它的析构函数会在强引用关系消失的时候调用

代码位于:frameworks/base/core/jni/android_view_SurfaceControl.cpp

static void nativeRelease(JNIEnv* env, jclass clazz, jlong nativeObject) {
    sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(nativeObject));
    // 强引用数 -1
    ctrl->decStrong((void *)nativeCreate);
}

当其强引用关系消失的时候,调用deconstructor:

代码位于:system/core/libutils/RefBase.cpp

void RefBase::decStrong(const void* id) const
{
    weakref_impl* const refs = mRefs;
    refs->removeStrongRef(id);
    const int32_t c = refs->mStrong.fetch_sub(1, std::memory_order_release);
    LOG_ALWAYS_FATAL_IF(BAD_STRONG(c), "decStrong() called on %p too many times",
            refs);
    if (c == 1) {
        std::atomic_thread_fence(std::memory_order_acquire);
        refs->mBase->onLastStrongRef(id);
        int32_t flags = refs->mFlags.load(std::memory_order_relaxed);
        if ((flags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) {
            delete this;
            // The destructor does not delete refs in this case.
        }
    }
    refs->decWeak(id);
}

Layer的销毁

Layer也继承自RefBase.cpp当其引用关系清空时,将会触发析构函数,进行Layer的销毁释放。Layer被handle持有,在SurfaceControl.cpp对象释放的时候,将会触发handle的释放:

SurfaceControl的析构

代码位于:frameworks/native/libs/gui/SurfaceControl.cpp

SurfaceControl::~SurfaceControl()
{
    // Trigger an IPC now, to make sure things
    // happen without delay, since these resources are quite heavy.
    mClient.clear();
    mHandle.clear();
    mBbq.clear();
    IPCThreadState::self()->flushCommands();
}

这里将Handle的引用进行了释放,来到sf端:

Handle触发析构,继承自LayerCleaner:

代码位于:frameworks/native/services/surfaceflinger/Layer.h

class LayerCleaner {
    sp<SurfaceFlinger> mFlinger;
    sp<Layer> mLayer;
    BBinder* mHandle;

protected:
    ~LayerCleaner() {
        // destroy client resources
        mFlinger->onHandleDestroyed(mHandle, mLayer);
    }

Layer引用清空

来到SurfaceFlinger.cpp,进行Handle销毁的回调,将Layer进行引用清空:

代码位于:frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp

void SurfaceFlinger::onHandleDestroyed(BBinder* handle, sp<Layer>& layer) {
    Mutex::Autolock lock(mStateLock);
    markLayerPendingRemovalLocked(layer);
    mBufferCountTracker.remove(handle);
    layer.clear();
    if (mTransactionTracing) {
        mTransactionTracing->onHandleRemoved(handle);
    }
}

Layer引用清空后,Layer触发析构:

Layer::~Layer() {
    sp<Client> c(mClientRef.promote());
    if (c != 0) {
        c->detachLayer(this);
    }

    mFlinger->onLayerDestroyed(this);
    
    if (mHadClonedChild) {
        mFlinger->mNumClones--;
    }
}

在SurfaceFlinger.cpp中清空该Layer的记录:

  • 从mOffscreenLayers集合中移除
  • mNumLayers总Layer数记录-1
void SurfaceFlinger::onLayerDestroyed(Layer* layer) {
    mNumLayers--;
    removeHierarchyFromOffscreenLayers(layer);
    if (!layer->isRemovedFromCurrentState()) {
        mScheduler->deregisterLayer(layer);
    }
    if (mTransactionTracing) {
        mTransactionTracing->onLayerRemoved(layer->getSequence());
    }
}

至此完成Layer的销毁,和资源的释放。

TODO:

多个SurfaceControl(nativeCopy) 都指向一个Layer,只有所有SurfaceControl都销毁,才会将Layer的引用清空,触发析构。跟踪该流程。

实际案例

BugFix:
在这里插入图片描述

问题原因:进入过分屏的Task,其Layer都无法触发析构,当mOffscreenLayers数量过高,总Layer数超过4096后将会创建SurfaceControl失败。

跟踪发现,SystemUI会通过nativeCopy构造一个SurfaceControl,其中的handle就指向Task的Layer。

进入分屏后,该SurfaceControl会被StageTaskListener中的StageTaskUnfoldController持有,当该Task销毁vanished()时,StageTaskUnfoldController并没有将其引用释放。发生内存泄漏:

代码位置:frameworks/base/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskUnfoldController.java

public void onTaskVanished(ActivityManager.RunningTaskInfo taskInfo) {
        // 这里条件不符合,直接return,导致没有触发后续的remove
        if (!taskInfo.hasParentTask()) return;

        AnimationContext context = mAnimationContextByTaskId.get(taskInfo.taskId);
        if (context != null) {
            final SurfaceControl.Transaction transaction = mTransactionPool.acquire();
            resetSurface(transaction, context);
            transaction.apply();
            mTransactionPool.release(transaction);
        }
        mAnimationContextByTaskId.remove(taskInfo.taskId);
    }

解决:

  • 方案1:取消折叠屏特性,不触发StageTaskUnfoldController的onTaskAppeared和onTaskVanished
  • 方案2: 调整逻辑,使得remove逻辑正常
  • 方案3: ShellTaskOrganizer中收到onTaskVanished最后,主动对SurfaceControl调用release()

更多framework实战干货,请关注下面“千里马学框架”

Android N中SurfaceView泄露的问题分析 最近遇到一个bug,现象为SurfaceView的Layer没有销毁,导致屏幕上一直显示该Layer。觉得该案例有点意思,故在此记录下分析过程及解决方法,供有一定framework基础的Rom开发人员参考。 现象 分析过程 首先最直接相关的模块是SurfaceFlinger,既然能看到,应该存在该Layer并且进行了合成,否则这里就有问题,用如下命令dump状态信息: 阅读详情

相关推荐

Unity Android游戏性能优化:从瓶颈定位到实战优化全攻略

在移动游戏开发中,性能优化是确保流畅用户体验的核心工程实践。其原理在于通过系统化的监控与分析,定位消耗计算资源的瓶颈点,如CPU过载、GPU渲染压力或内存管理不当。这项技术的价值在于能将抽象的性能问题量化,将卡顿、掉帧等体验问题转化为可测量、可解决的工程指标,从而显著提升游戏在目标设备上的稳定性和帧率。典型的应用场景包括解决Android真机与Unity编辑器间的性能差异、应对中低端设备的热节流问题,以及治理因垃圾回收(GC)导致的周期性卡顿。例如,通过集成类似 **metric帧率记录器** 的工具进行长

weixin_34006468的博客 358

与Flutter第一次亲密接触-Android 视角

作者简介 万坤,5年安卓开发经验,16年加入饿了么,现任职饿了么资深安卓开发工程师,负责饿了么物流安卓相关APP线上的高稳定运行。 前言 Flutter在今年6月份发布第一个Release预览版以来,开发热度呈现了井喷式的爆发。Github上Flutter项目的小星星也已经涨到了3.6万了,同时国内闲鱼团队已经将Flutter用到了业务中并上线运行。可以说Flutter已经有了非常成熟的使用环...

weixin_34090562的博客 333

DyaPlex:流式全双工语音-动作协同感知架构解析

流式处理与全双工交互是现代人机交互的核心基础能力,其本质是在毫秒级时间尺度上实现多模态信号的低延迟采集、异步调度与动态融合。传统ASR依赖语音转文本的串行范式,难以应对真实场景中语音模糊、动作先行、意图隐含等挑战;而协同感知技术则通过建模语音、触控、眼动、IMU等跨模态信号间的条件依赖关系,提升语义理解鲁棒性。DyaPlex提出的时序对齐门控机制(TAGM)和分段重叠采样(SOS)等方法,将响应粒度从帧级推进至子帧级,支撑远程医疗、工业AR、无障碍教育等对实时性与意图准确性双高要求的落地场景。

weixin_30414305的博客 371

surfaceflinger中traverseInZOrder调用流程

在SurfaceFlinger.cpp里可以看到很多 traverseInZOrder的调用,比如dumpsys的调用, mCurrentState.traverseInZOrder([&](Layer* layer) { layer->miniDump(result, hwcId); }); 还有 status_t SurfaceFlinger::getLayerDebugInfo(std::vector<Laye...

aaajj的专栏 1223

避坑指南:SurfaceFlinger的Layer泄漏如何吃掉你的GPU内存(附Android 13最新调试技巧)

本文深入剖析了Android 13系统中SurfaceFlinger的Layer泄漏问题,揭示了其导致GPU内存被持续消耗的根源。文章提供了从监控、诊断到修复的完整实战方案,包括使用dumpsys、Perfetto等工具进行排查,并针对分屏模式、Dialog等典型泄漏场景给出了具体的代码修复示例和最佳实践,帮助开发者有效解决这一系统级性能顽疾。

b0c1d2的博客 323

从Blender舞步到夜空画卷:基于Pix飞控的无人机编队灯光秀全链路开发实践

本文详细介绍了基于Pixhawk飞控的无人机编队灯光秀全链路开发实践。从Blender三维动画设计、QGroundControl地面站二次开发与MAVLink通信桥接,到PX4飞控的OFFBOARD模式路径控制与LED灯光驱动实现,最后通过Gazebo仿真验证并完成真机组装与首飞。文章为无人机爱好者提供了一套完整的、从创意设计到夜空执行的开源解决方案,重点阐述了多机同步与灯光控制的核心技术挑战与应对策略。

zeta9的博客 586

GraphicBufferProducer的引用关系

最近碰到一个问题:压测SurfaceFlinger 会crash掉,提示 383 783 F SurfaceFlinger: Suspected IGBP leak: 4097 IGBPs (4096 max), 49 Layers 本文侧重点是介绍IGBP的创建与销毁。 一. GraphicBufferProducer 的server端 该log是SurfaceFlinger.cpp中打印的,其代码段如下 status_t SurfaceFlinger::addClientLayer..

入琞的博客 4719

跨厂商网络设备的RADIUS认证:Windows NPS的兼容性与最佳实践

本文详细探讨了Windows NPS在多厂商网络环境中的RADIUS认证实践,特别针对华为、华三、思科等主流设备的兼容性问题提供解决方案。从基础配置到高级优化,涵盖VSA属性映射、认证协议选择及安全加固措施,帮助企业实现统一身份认证并提升网络安全性。

weixin_29213827的博客 423

SurfaceFlinger中Layer泄露如何排查解决?-vip学员作业

在AOSP 13中,切换壁纸时出现ImageWallpaper Layer内存泄漏,导致mOffscreenLayers持续增长,可能突破4096层上限引发新图层创建失败。问题根源在于壁纸销毁后未正确从offscreen集合移除,因Layer无父级但未被及时清理。与其他窗口不同,壁纸生命周期管理特殊,且未主动释放。修复需在壁纸销毁时显式从mOffscreenLayers移除对应Layer。排查流程包括dumpsys分析、代码追踪offscreen添加逻辑、定位异常残留。建议在WallpaperService

liaosongmao1的专栏 6

动手学Moveit2 | 运行配置好的机械臂功能demo

通过这个小demo你可以直观的感受moveit2的强大,但还有很多需要我们探索的,比如机械臂是如何规划的,规划的过程中如何结合环境信息,规划的时候机械臂如何求解,如何和真实的机械臂对接等等,这些都需要你来进一步探索,今天就到这里,明天给大家秀一下小仙女焊的fishbot运控板。

生活不止眼前的苟且 8883

QCPColorMap实现瀑布图

QCPColorMap实现真正的瀑布图

pf1873252141的博客 5275

Flutter鸿蒙应用黑屏白屏与OOM内存问题排查实战手册

在跨平台开发中,Flutter凭借高性能和一致体验成为众多团队的选择。然而当Flutter应用运行在鸿蒙(OpenHarmony)原生环境时,由于渲染链路、窗口管理及生命周期与Android存在根本差异,界面异常与内存问题频发,黑屏、白屏、OOM闪退和内存持续增长成为线上反馈的高频痛点。理解其背后的运行原理,即ArkUI窗口、FlutterEngine与鸿蒙图形栈的协作机制,是高效定位问题的关键。掌握基于HDC、hilog、DevTools等工具的内存归因与堆快照分析方法,能够帮助开发者快速识别Dart堆与

weixin_34279184的博客 843

【深度学习|语义分割之UNet】如何使用ResNet50 作为 U-Net 网络的骨干网络(backbone)并使用预训练的 ResNet50 模型。附代码及解读。

【深度学习|语义分割之UNet】如何使用ResNet50 作为 U-Net 网络的骨干网络(backbone)并使用预训练的 ResNet50 模型。附代码及解读。

985小水博的摸鱼日常 3091

高通Camera驱动中ION与DMA-BUF内存共享机制详解

ION和DMA-BUF是Android系统中实现硬件模块间零拷贝内存共享的核心机制,其本质是Linux内核为异构处理器(ISP、GPU、Display)提供的统一内存管理与跨进程传递方案。ION负责按硬件需求(如物理连续、cache一致性、安全隔离)分配内存池,DMA-BUF则将其封装为可安全传递的文件描述符,并通过fence机制保障同步。该组合解决了高通平台Camera数据流中预览卡顿、花屏、黑屏等典型问题,广泛应用于Camera HAL、SurfaceFlinger、HWC及AI视觉流水线。本文聚焦实际

weixin_33831673的博客 426

yolo 图像检测、关键点检测单摄像头测量物体尺寸长度大小

new_distance/real_size (待求物体像素距离与实际距离比值)= distance / metric_length (参照物像素距离与实际距离比值)然后运行size_demo进行要测量的物体进行关节点检测距离;metric_length是上面耳机选取的两个点的实际物理距离,大概6cm;这里用的windows。通过关键点检测识别物体关键点的像素距离,然后参考比例尺计算实际距离。2)关键点算法这里用的现有的进行测试,实际场景需要自己训练。这里拿这模型推理出的关键点坐标进行后续长度计算。

weixin_42357472的博客 2527

LeetCode --- 937. Reorder Data in Log Files 解题报告

You are given an array oflogs. Each log is a space-delimited string of words, where the first word is theidentifier. There are two types of logs: Letter-logs: All words (except the identifier) consist of lowercase English letters. Digit-logs: All word..

杨鑫newlife的专栏 427

Rockchip平台scrcpy黑屏根因:DMA-BUF泄漏深度解析

DMA-BUF是Linux内核实现硬件加速器(GPU/VPU/ISP)零拷贝内存共享的核心机制,其引用计数模型要求用户空间与驱动层严格配对调用dma_buf_get/dma_buf_put。当Rockchip VPU驱动在异常路径下遗漏dma_buf_put,会导致物理页锁死、IOMMU地址空间耗尽,引发无ANR、无Crash日志的静默黑屏——这正是scrcpy投屏卡死的本质原因。该问题广泛存在于RK3288/RK3399等工控HMI设备中,典型表现为‘运行1–2小时后屏幕冻结但App仍响应’。本文结合内核

weixin_33946020的博客 418

基于Simulink和Control System Toolbox的线控转向(Steer-by-Wire)系统设计

通过上述步骤,我们成功设计并实现了基于 Simulink 和 Control System Toolbox 的线控转向(Steer-by-Wire)系统。该系统能够接收来自方向盘的角度指令,经过控制器处理后,驱动转向执行器(如电动机),实现对车辆前轮转向角度的精确控制。通过虚拟场景仿真、硬件在环测试和实车测试,验证了系统的响应速度、控制精度、车辆稳定性和实时性能,并通过参数优化进一步提升了系统的性能。

MHD0815的博客 551

Android人脸检测实战:性能调优与碎片化适配指南

人脸检测是移动端视觉应用的基础能力,其本质是在受限硬件上完成实时图像特征提取与定位。核心原理依赖于YUV格式处理、NEON加速的LBP/ASM模型及GPU纹理零拷贝优化。技术价值体现在低延迟(<30ms)、高稳定性(抗OOM/偏移)与跨ROM兼容性,广泛应用于活体验证、考勤打卡、AR互动等场景。然而真实落地中,Google Mobile Vision API的表现受设备芯片、系统定制、相机HAL层差异显著影响——如华为EMUI的帧时间偏移、小米HyperOS的模块加载延迟、OPPO ColorOS的ID禁用

weixin_30363509的博客 415

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

SurfaceFinger layer创建过程

SurfaceFlinger::setTransactionState中比较复杂容易忽略将TransactionState state放入mTransactionQueue的过程,mTransactionQueue在后面创建hwc layer的时候会用到。mClient->createSurface会调用到android12\frameworks\native\services\surfaceflinger\Client.cpp 中Client::createSurface。app端创建Surface。

IT先森 1714

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

通过Hardware Layer提高动画性能

通过Hardware Layer提高动画性能项目中越来越多的动画,越来越多的效果导致了应用性能越来越低。该如何提升。 简介在View播放动画的过程中每一帧都需要被重绘。如果使用view layers,就不用每帧都去重绘,因为View渲染一旦离开屏幕缓冲区就可以被重用。而且,hardware layers会在GPU上缓存,这样就会让一些动画过程中的操作变得更快。通过hardware layers可

Charon_Chui的专栏 1149

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

surfaceflinger刷新动作和client合成

首先来看看,createlayer这个是后面刷新的基本。createsurface生成surface的时候会调用createlayer status_t SurfaceFlinger::createLayer( const String8& name, const sp<Client>& client, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, .

bruk_spp的博客 1620

iOS开发之图形渲染分析、离屏渲染、当前屏幕渲染、On-Screen Rendering、Off-Screen Rendering

这次主要要讲一些关于绘图方面的东西,涉及的方面可能会比较多一点,也是前段时间项目中有不少这方面的知识所以花了点时间研究了一下。文章的内容主要分为两部分,第一部分是关于iOS上一个Chart的第三方库的一些进阶使用;第二部分是在第一部分上研究的iOS上的绘图原理以及性能方面的探索。这篇文章的目的主要是为以后讲关于绘图方面的知识抛砖引玉吧,因为后面的时间会讲一些关于性能监测以及性能优化方面的内容,绘图

zhonggaorong的专栏 7820

AndroidO 图形框架下应用绘图过程——Surface创建

Android图形框架在前几年已经分析过了,不过,随着Android版本的升级,虽然框架主体未变,但有些细节变动还是比较大的,应网友要求,今天再次以AndroidO为基础,重新介绍图形框架实现,Android图形框架包括以下三大部分:1. 应用绘图;2. SurfaceFlinger混合图层;3. Hwc Hal实现本文首先介绍AndroidO下应用的绘图过程,应用绘图也分为以下几个步骤:sp&l...

深入剖析Android系统 9521

Flutter 性能优化

Flutter 作为目前最火爆的移动端跨平台框架,能够帮助开发者通过一套代码库高效地构建多平台的精美应用,并支持移动、Web、桌面和嵌入式平台。对于 Android 来说,Flutter 能够创作媲美原生的高性能应用,但是,在较为复杂的 App 中,使用 Flutter 开发也很难避免产生各种各样的性能问题。在这篇文章中,我将和你一起全方位地深入探索 Flutter 性能优化的疆域。以 profile 模式启动应用,如果是混合 Flutter 应用,在 flutter/packages/flutter_to

Dream It Possible 6454
上一篇: User手机上如何抓取界面的布局uiautomatorviewer
下一篇: 千里马直播通知:高阶WMS显示相关疑难问题自由窗口/黑屏/部分黑问题案例
千里马学框架
博客等级 码龄6年 1万+粉丝 651原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千里马学框架

帮助你了,就请我喝杯咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值