Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c5686802 authored by Valerie Hau's avatar Valerie Hau
Browse files

When destroying layer, add children to offscreen layers

If a layer is destroyed, make sure all children are added to the
offscreen layers.  Otherwise, we may dangle a layer that is neither in
current state nor in offscreen layers.
Bug: 141111965
Test: build, boot, manual

Change-Id: Iec6788f10a24cb63faa9b40f246cbde3770d24a7
parent d0d28e31
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -664,6 +664,15 @@ public:
                                  const LayerVector::Visitor& visitor);

    size_t getChildrenCount() const;

    // ONLY CALL THIS FROM THE LAYER DTOR!
    // See b/141111965.  We need to add current children to offscreen layers in
    // the layer dtor so as not to dangle layers.  Since the layer has not
    // committed its transaction when the layer is destroyed, we must add
    // current children.  This is safe in the dtor as we will no longer update
    // the current state, but should not be called anywhere else!
    LayerVector& getCurrentChildren() { return mCurrentChildren; }

    void addChild(const sp<Layer>& layer);
    // Returns index if removed, or negative value otherwise
    // for symmetry with Vector::remove
+14 −3
Original line number Diff line number Diff line
@@ -3717,9 +3717,6 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, int
    }

    if (currentMode == HWC_POWER_MODE_OFF) {
        // Turn on the display
        // TODO: @vhau temp fix only!  See b/141111965
        mTransactionCompletedThread.clearAllPending();
        getHwComposer().setPowerMode(*displayId, mode);
        if (display->isPrimary() && mode != HWC_POWER_MODE_DOZE_SUSPEND) {
            setVsyncEnabledInHWC(*displayId, mHWCVsyncPendingState);
@@ -5500,6 +5497,20 @@ void SurfaceFlinger::onLayerFirstRef(Layer* layer) {

void SurfaceFlinger::onLayerDestroyed(Layer* layer) {
    mNumLayers--;
    removeFromOffscreenLayers(layer);
}

// WARNING: ONLY CALL THIS FROM LAYER DTOR
// Here we add children in the current state to offscreen layers and remove the
// layer itself from the offscreen layer list.  Since
// this is the dtor, it is safe to access the current state.  This keeps us
// from dangling children layers such that they are not reachable from the
// Drawing state nor the offscreen layer list
// See b/141111965
void SurfaceFlinger::removeFromOffscreenLayers(Layer* layer) {
    for (auto& child : layer->getCurrentChildren()) {
        mOffscreenLayers.emplace(child.get());
    }
    mOffscreenLayers.erase(layer);
}

+2 −0
Original line number Diff line number Diff line
@@ -313,6 +313,8 @@ public:
    void onLayerFirstRef(Layer*);
    void onLayerDestroyed(Layer*);

    void removeFromOffscreenLayers(Layer* layer);

    TransactionCompletedThread& getTransactionCompletedThread() {
        return mTransactionCompletedThread;
    }
+0 −9
Original line number Diff line number Diff line
@@ -189,15 +189,6 @@ status_t TransactionCompletedThread::finalizePendingCallbackHandles(
    return NO_ERROR;
}

void TransactionCompletedThread::clearAllPending() {
    std::lock_guard lock(mMutex);
    if (!mRunning) {
        return;
    }
    mPendingTransactions.clear();
    mConditionVariable.notify_all();
}

status_t TransactionCompletedThread::registerUnpresentedCallbackHandle(
        const sp<CallbackHandle>& handle) {
    std::lock_guard lock(mMutex);
+0 −2
Original line number Diff line number Diff line
@@ -70,8 +70,6 @@ public:
    // Notifies the TransactionCompletedThread that a pending CallbackHandle has been presented.
    status_t finalizePendingCallbackHandles(const std::deque<sp<CallbackHandle>>& handles);

    void clearAllPending();

    // Adds the Transaction CallbackHandle from a layer that does not need to be relatched and
    // presented this frame.
    status_t registerUnpresentedCallbackHandle(const sp<CallbackHandle>& handle);