SufraceFlinger图像合成原理(5)-Layer 合成数据流

113 阅读11分钟

5.1 应用端绘制

应用端渲染线程绘制完成后,通过BufferQueueProducer.queueBuffer将绘制后的buffer 句柄传给SF 去合成。

具体流程:

BufferQueueProducer.queueBuffer

-> ConsumerBase::onFrameAvailable

-> BufferQueueLayer::onFrameAvailable

5.2 SurfaceFlinger 端合成

继续看下BufferQueueLayer::onFrameAvailable方法:


void BufferQueueLayer::onFrameAvailable(const BufferItem& item) {
    const int32_t layerId = getSequence();
    const uint64_t bufferId = item.mGraphicBuffer->getId();
    mFlinger->mFrameTracer->traceTimestamp(layerId, bufferId, item.mFrameNumber, systemTime(),
                                           FrameTracer::FrameEvent::QUEUE);
    mFlinger->mFrameTracer->traceFence(layerId, bufferId, item.mFrameNumber,
                                       std::make_shared<FenceTime>(item.mFence),
                                       FrameTracer::FrameEvent::ACQUIRE_FENCE);

    ATRACE_CALL();
    // Add this buffer from our internal queue tracker
    { // Autolock scope
        //将待合成BufferItem 放入容器mQueueItems
        mQueueItems.push_back(item);
        //这个变量会在SurfaceFlinger 收到invalidate 消息后用到,根据改值是否大于0 ,用于判断是否需要合成
        mQueuedFrames++;
        if (item.mGraphicBuffer != nullptr) {
            ALOGE("onFrameAvailable  = %s, %d ",getName().c_str(), item.mGraphicBuffer->getHeight());
        }

        // Wake up any pending callbacks
        mLastFrameNumberReceived = item.mFrameNumber;
        mQueueItemCondition.broadcast();
    }

    mFlinger->mInterceptor->saveBufferUpdate(layerId, item.mGraphicBuffer->getWidth(),
                                             item.mGraphicBuffer->getHeight(), item.mFrameNumber);
   //发起合成申请
    mFlinger->signalLayerUpdate();
    mConsumer->onBufferAvailable(item);
}

onFrameAvailable方法主要是:

  • 记录待合成buffer
  • 向SF申请合成

SF 合成主要是处理两个消息:

  • Invalidate
  • Refresh
  1. Invalidate 消息处理

当Vsync 到来时会先处理Invalidate消息:

a. SurfaceFlinger::handleMessageInvalidate()

handleMessageTransaction()

flushTransactionQueues() //system server 或应用端Transaction.apply在此处生效

commitTransaction() //mDrawingState = mCurrentState;

  • mCurrentState 应用传来的layer 状态集合
  • mDrawingState SF 待合成的layer 状态集合

b. SurfaceFlinger::handlePageFlip()

bool SurfaceFlinger::handlePageFlip()
{
    ATRACE_CALL();
    ALOGV(" handlePageFlip");

    nsecs_t latchTime = systemTime();

    bool visibleRegions = false;
    bool frameQueued = false;
    bool newDataLatched = false;

    const nsecs_t expectedPresentTime = mExpectedPresentTime.load();

    // Store the set of layers that need updates. This set must not change as
    // buffers are being latched, as this could result in a deadlock.
    // Example: Two producers share the same command stream and:
    // 1.) Layer 0 is latched
    // 2.) Layer 0 gets a new frame
    // 2.) Layer 1 gets a new frame
    // 3.) Layer 1 is latched.
    // Display is now waiting on Layer 1's frame, which is behind layer 0's
    // second frame. But layer 0's second frame could be waiting on display.
    mDrawingState.traverse([&](Layer* layer) {
        if (layer->hasReadyFrame()) {
            frameQueued = true;
            //这里遍历所有layer 判断是否需要先在显示
            if (layer->shouldPresentNow(expectedPresentTime)) {
                mLayersWithQueuedFrames.push_back(layer);
            } else {
                ATRACE_NAME("!layer->shouldPresentNow()");
                layer->useEmptyDamage();
            }
        } else {
            layer->useEmptyDamage();
        }
    });
    
    if (!mLayersWithQueuedFrames.empty()) {
    // mStateLock is needed for latchBuffer as LayerRejecter::reject()
    // writes to Layer current state. See also b/119481871
    Mutex::Autolock lock(mStateLock);

    for (auto& layer : mLayersWithQueuedFrames) {
        if (layer->latchBuffer(visibleRegions, latchTime, expectedPresentTime)) {
            mLayersPendingRefresh.push_back(layer);
        }
        layer->useSurfaceDamage();
        if (layer->isBufferLatched()) {
            newDataLatched = true;
        }
    }
}
  • 遍历所有layer 将需要立即合成的layer 放入容器mLayersWithQueuedFrames
  • 遍历待合成容器mLayersWithQueuedFrames,取出对应的buffer

继续看下是否立即合成条件:shouldPresentNow

frameworks/native/services/surfaceflinger/BufferQueueLayer.cpp

bool BufferQueueLayer::shouldPresentNow(nsecs_t expectedPresentTime) const {
    if (getSidebandStreamChanged() || getAutoRefresh()) {
        return true;
    }

    if (!hasFrameUpdate()) {     
        return false;
    }
    
   

这里关键是hasFrameUpdate() 方法

bool BufferQueueLayer::hasFrameUpdate() const {
    return mQueuedFrames > 0;
}

应用queueBuffer 后,buffer 还没有被acquire ,mQueuedFrames会大于0

上面遍历mDrawingState 取出待绘制layer,放入容器 mLayersWithQueuedFrames

遍历 mLayersWithQueuedFrames调用latchBuffer

bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime,
                              nsecs_t expectedPresentTime) {
    ATRACE_CALL();

    bool refreshRequired = latchSidebandStream(recomputeVisibleRegions);

    if (refreshRequired) {
        return refreshRequired;
    }

    if (!hasReadyFrame()) {
        return false;
    }


    status_t err = updateTexImage(recomputeVisibleRegions, latchTime, expectedPresentTime);

继续看updateTexImage

BufferQueueLayer::updateTexImage

-> BufferLayerConsumer::updateTexImage

status_t BufferLayerConsumer::updateTexImage(BufferRejecter* rejecter, nsecs_t expectedPresentTime,
                                             bool* autoRefresh, bool* queuedBuffer,
                                             uint64_t maxFrameNumber) {
    ATRACE_CALL();
    BLC_LOGV("upd ateTexImage");
    Mutex::Autolock lock(mMutex);

    BufferItem item;

    // Acquire the next buffer.
    // In asynchronous mode the list is guaranteed to be one buffer
    // deep, while in synchronous mode we use the oldest buffer.
    status_t err = acquireBufferLocked(&item, expectedPresentTime, maxFrameNumber);
    if (err != NO_ERROR) {
        if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
            err = NO_ERROR;
        } else if (err == BufferQueue::PRESENT_LATER) {
            // return the error, without logging
        } else {
            BLC_LOGE("updateTexImage: acquire failed: %s (%d)", strerror(-err), err);
        }
        return err;
    }
    if (item.mGraphicBuffer != nullptr) {
    ALOGE("lzh100 updateTexImage  = %s, %d ",mLayer->getName().c_str(), item.mGraphicBuffer->getHeight());
    }

    if (autoRefresh) {
        *autoRefresh = item.mAutoRefresh;
    }

    if (queuedBuffer) {
        *queuedBuffer = item.mQueuedBuffer;
    }

    // We call the rejecter here, in case the caller has a reason to
    // not accept this buffer.  This is used by SurfaceFlinger to
    // reject buffers which have the wrong size
    int slot = item.mSlot;
    if (rejecter && rejecter->reject(mSlots[slot].mGraphicBuffer, item)) {
        releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer);
        return BUFFER_REJECTED;
    }

    // Release the previous buffer.
    err = updateAndReleaseLocked(item, &mPendingRelease);


    return err;
}
  • acquireBufferLocked 获取应用端queue 的buffer
  • updateAndReleaseLocked更新buffer相关信息,即BufferItem对象
status_t BufferLayerConsumer::updateAndReleaseLocked(const BufferItem& item,
                                                     PendingRelease* pendingRelease) {
    status_t err = NO_ERROR;

    int slot = item.mSlot;

    BLC_LOGV("updateAndRelease: (slot=%d buf=%p) -> (slot=%d buf=%p)", mCurrentTexture,
             (mCurrentTextureBuffer != nullptr && mCurrentTextureBuffer->graphicBuffer() != nullptr)
                     ? mCurrentTextureBuffer->graphicBuffer()->handle
                     : 0,
             slot, mSlots[slot].mGraphicBuffer->handle);

    // Hang onto the pointer so that it isn't freed in the call to
    // releaseBufferLocked() if we're in shared buffer mode and both buffers are
    // the same.

    std::shared_ptr<Image> nextTextureBuffer;
    {
        std::lock_guard<std::mutex> lock(mImagesMutex);
        nextTextureBuffer = mImages[slot];
    }

    // release old buffer
    if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
        if (pendingRelease == nullptr) {
            status_t status =
                    releaseBufferLocked(mCurrentTexture, mCurrentTextureBuffer->graphicBuffer());
            if (status < NO_ERROR) {
                BLC_LOGE("updateAndRelease: failed to release buffer: %s (%d)", strerror(-status),
                         status);
                err = status;
                // keep going, with error raised [?]
            }
        } else {
            pendingRelease->currentTexture = mCurrentTexture;
            pendingRelease->graphicBuffer = mCurrentTextureBuffer->graphicBuffer();
            pendingRelease->isPending = true;
        }
    }

    // Update the BufferLayerConsumer state.
    mCurrentTexture = slot;
    mCurrentTextureBuffer = nextTextureBuffer;

将buffer 更新到mCurrentTextureBuffer,代表当前Layer对应的待合成buffer, 后面Layer ::getBuffer 返回的就是mCurrentTextureBuffer, 流程如下:

sp<GraphicBuffer> BufferLayer::getBuffer() const {
    return mBufferInfo.mBuffer;
}

看下mBufferInfo.mBuffer如何赋值,上面acquireBuffer 后updateTexImage中会调用updateAndReleaseLocked,再调用到updateActiveBuffer更新Buffer,所以这里把待合成的buffer 赋值给mBufferInfo.mBuffer

status_t BufferQueueLayer::updateActiveBuffer() {
    // update the active buffer
    mPreviousBufferId = getCurrentBufferId();
    mBufferInfo.mBuffer =
            mConsumer->getCurrentBuffer(&mBufferInfo.mBufferSlot, &mBufferInfo.mFence);

    if (mBufferInfo.mBuffer == nullptr) {
        // this can only happen if the very first buffer was rejected.
        return BAD_VALUE;
    }
    return NO_ERROR;
}

最终getBuffer其是就是mCurrentTextureBuffer

sp<GraphicBuffer> BufferLayerConsumer::getCurrentBuffer(int* outSlot, sp<Fence>* outFence) const {
    return mCurrentTextureBuffer == nullptr ? nullptr : mCurrentTextureBuffer->graphicBuffer();
}

到目前为止通过acquireBuffer获取到应用绘制的buffer 并更新在了Layer中的mBufferInfo.mBuffer可以通过方法getBuffer() 获取buffer

c. 最后如果需要refresh 触发refresh,发送refresh消息的前提:

  • 有Transaction更新
  • 有buffer 更新
 void SurfaceFlinger::onMessageInvalidate(nsecs_t expectedVSyncTime) {
 ... ...
      bool refreshNeeded;
      {
          ConditionalLockGuard<std::mutex> lock(mTracingLock, mTracingEnabled);
  
          refreshNeeded = handleMessageTransaction();
          refreshNeeded |= handleMessageInvalidate();
          if (mTracingEnabled) {
              mAddCompositionStateToTrace =
                      mTracing.flagIsSetLocked(SurfaceTracing::TRACE_COMPOSITION);
              if (mVisibleRegionsDirty && !mAddCompositionStateToTrace) {
                  mTracing.notifyLocked("visibleRegionsDirty");
              }
          }
      }
        ... ...
      if (refreshNeeded && CC_LIKELY(mBootStage != BootStage::BOOTLOADER)) {
          signalR efresh();
      }
 }

2. 后继续处理refresh 消息:

void SurfaceFlinger::onMessageRefresh() {
    ATRACE_CALL();

    mRefreshPending = false;

    compositionengine::CompositionRefreshArgs refreshArgs;
    const auto& displays = ON_MAIN_THREAD(mDisplays);
    refreshArgs.outputs.reserve(displays.size());
    for (const auto& [_, display] : displays) {
        refreshArgs.outputs.push_back(display->getCompositionDisplay());
    }
    mDrawingState.traverseInZOrder([&refreshArgs](Layer* layer) {
        if (auto layerFE = layer->getCompositionEngineLayerFE()) {
            refreshArgs.layers.push_back(layerFE);
        }
    });
    ...
    mCompositionEngine->present(refreshArgs);
    }

SurfaceFlinger::onMessageRefresh()

->CompositionEngine::present

->Output::prepare

->Output::rebuildLayerStacks

从 rebuildLayerStacks 就是要合成layer 的筛选过程,注意rebuildLayerStacks的数据来源也是mDrawingState

frameworks/native/services/surfaceflinger/CompositionEngine/src/Output.cpp

void Output::rebuildLayerStacks(const compositionengine::CompositionRefreshArgs& refreshArgs,
                                LayerFESet& layerFESet) {
    ATRACE_CALL();
    ALOGV(__FUNCTION__);

    auto& outputState = editState();

    // Do nothing if this output is not enabled or there is no need to perform this update
    if (!outputState.isEnabled || CC_LIKELY(!refreshArgs.updatingOutputGeometryThisFrame)) {
        return;
    }

    // Process the layers to determine visibility and coverage
    compositionengine::Output::CoverageState coverage{layerFESet};
    collectVisibleLayers(refreshArgs, coverage);

    // Compute the resulting coverage for this output, and store it for later
    const ui::Transform& tr = outputState.transform;
    Region undefinedRegion{outputState.bounds};
    undefinedRegion.subtractSelf(tr.transform(coverage.aboveOpaqueLayers));

    outputState.undefinedRegion = undefinedRegion;
    outputState.dirtyRegion.orSelf(coverage.dirtyRegion);
}

继续看collectVisibleLayers:

void Output::collectVisibleLayers(const compositionengine::CompositionRefreshArgs& refreshArgs,
                                  compositionengine::Output::CoverageState& coverage) {
    // Evaluate the layers from front to back to determine what is visible. This
    // also incrementally calculates the coverage information for each layer as
    // well as the entire output.
    for (auto layer : reversed(refreshArgs.layers)) {
        // Incrementally process the coverage for each layer
        ensureOutputLayerIfVisible(layer, coverage);

        // TODO(b/121291683): Stop early if the output is completely covered and
// no more layers could even be visible underneath the ones on top.
    }

    setReleasedLayers(refreshArgs);

    finalizePendingOutputLayers();

    // Generate a simple Z-order values to each visible output layer
    uint32_t zOrder = 0;
    for (auto* outputLayer : getOutputLayersOrderedByZ()) {
        outputLayer->editState().z = zOrder++;
    }
}

逆序遍历,也就是从上到下遍历,决定哪个layer 是可见的以及计算赃区:

void Output::ensureOutputLayerIfVisible(sp<compositionengine::LayerFE>& layerFE,
                                        compositionengine::Output::CoverageState& coverage) {
                                        
// Only consider the layers on the given layer stack
//只计算当前display 的layer
if (!belongsInOutput(layerFE)) {
    return;
}

... ...
    /*
     * shadowRegion: Region cast by the layer's shadow.
     */
    Region shadowRegion;

    const ui::Transform& tr = layerFEState->geomLayerTransform;

    // Get the visible region
    // TODO(b/121291683): Is it worth creating helper methods on LayerFEState
// for computations like this?
    const Rect visibleRect(tr.transform(layerFEState->geomLayerBounds));
    visibleRegion.set(visibleRect);

... ... 

    // compute the opaque region
    const auto layerOrientation = tr.getOrientation();
    if (layerFEState->isOpaque && ((layerOrientation & ui::Transform::ROT_INVALID) == 0)) {
        // If we one of the simple category of transforms (0/90/180/270 rotation
        // + any flip), then the opaque region is the layer's footprint.
        // Otherwise we don't try and compute the opaque region since there may
        // be errors at the edges, and we treat the entire layer as
        // translucent.
        opaqueRegion.set(visibleRect);
    }

    // Clip the covered region to the visible region
    // aboveCoveredLayers计代表目前被覆盖的区域,用于遍历更低层级时可见区域去掉被覆盖的区域
    //第一层时,aboveCoveredLayers为空,coveredRegion也是为空
    coveredRegion = coverage.aboveCoveredLayers.intersect(visibleRegion);

    // Update accumAboveCoveredLayers for next (lower) layer
    //更新aboveCoveredLayers,该层之下的Layer都被该层Layer覆盖,所以这里和可见区域做一个或操纵,最下面的区域被覆盖的越大
    coverage.aboveCoveredLayers.orSelf(visibleRegion);

    // subtract the opaque region covered by the layers above us
    //减去我们上面的图层覆盖的不透明区域
    visibleRegion.subtractSelf(coverage.aboveOpaqueLayers);

    if (visibleRegion.isEmpty()) {
        return;
    }

    // Get coverage information for the layer as previously displayed,
    // also taking over ownership from mOutputLayersorderedByZ.
    auto prevOutputLayerIndex = findCurrentOutputLayerForLayer(layerFE);
    auto prevOutputLayer =
            prevOutputLayerIndex ? getOutputLayerOrderedByZByIndex(*prevOutputLayerIndex) : nullptr;

    //  Get coverage information for the layer as previously displayed
    // TODO(b/121291683): Define kEmptyRegion as a constant in Region.h
const Region kEmptyRegion;
    const Region& oldVisibleRegion =
            prevOutputLayer ? prevOutputLayer->getState().visibleRegion : kEmptyRegion;
    const Region& oldCoveredRegion =
            prevOutputLayer ? prevOutputLayer->getState().coveredRegion : kEmptyRegion;

    // compute this layer's dirty region
    //开始计算脏区
    Region dirty;
    //contentDirty表示Layer的可见区域被修改了
    if (layerFEState->contentDirty) {
        // we need to invalidate the whole region
        dirty = visibleRegion;
        // as well, as the old visible region
        dirty.orSelf(oldVisibleRegion);
   //如果contentDirty没有被修改,开始计算暴露出来的区域 exposedRegion
    } else {
        /* compute the exposed region:
         *   the exposed region consists of two components:
         *   1) what's VISIBLE now and was COVERED before
         *   2) what's EXPOSED now less what was EXPOSED before
         *
         * note that (1) is conservative, we start with the whole visible region
         * but only keep what used to be covered by something -- which mean it
         * may have been exposed.
         *
         * (2) handles areas that were not covered by anything but got exposed
         * because of a resize.
         *
         */
         //暴露区域包含两个部分:1是之前被覆盖了,但是先在可见的区域,
         //第二个是处理没有被覆盖但是因为resize 导致的暴露
        const Region newExposed = visibleRegion - coveredRegion;
        const Region oldExposed = oldVisibleRegion - oldCoveredRegion;
        dirty = (visibleRegion & oldCoveredRegion) | (newExposed - oldExposed);
    }
    //脏区就是被把暴露区域减去被覆盖区域
    dirty.subtractSelf(coverage.aboveOpaqueLayers);

    // accumulate to the screen dirty region
    //更新屏幕脏区,保存在coverage
    coverage.dirtyRegion.orSelf(dirty);

    // Update accumAboveOpaqueLayers for next (lower) layer
    coverage.aboveOpaqueLayers.orSelf(opaqueRegion);

    // Compute the visible non-transparent region
    Region visibleNonTransparentRegion = visibleRegion.subtract(transparentRegion);

    // Perform the final check to see if this layer is visible on this output
    // TODO(b/121291683): Why does this not use visibleRegion? (see outputSpaceVisibleRegion below)
const auto& outputState = getState();
    Region drawRegion(outputState.transform.transform(visibleNonTransparentRegion));
    drawRegion.andSelf(outputState.bounds);
    if (drawRegion.isEmpty()) {
        return;
    }

    Region visibleNonShadowRegion = visibleRegion.subtract(shadowRegion);
 
    // The layer is visible. Either reuse the existing outputLayer if we have
    // one, or create a new one if we do not.
    //创建OutputLayer, 将可见layer存到mCurrentOutputLayersOrderedByZ、mPendingOutputLayersOrderedByZ
    auto result = ensureOutputLayer(prevOutputLayerIndex, layerFE);

    // Store the layer coverage information into the layer state as some of it
    // is useful later.
    auto& outputLayerState = result->editState();
    outputLayerState.visibleRegion = visibleRegion;
    outputLayerState.visibleNonTransparentRegion = visibleNonTransparentRegion;
    outputLayerState.coveredRegion = coveredRegion;
    outputLayerState.outputSpaceVisibleRegion =
            outputState.transform.transform(visibleNonShadowRegion.intersect(outputState.viewport));
    outputLayerState.shadowRegion = shadowRegion;
}

OutputLayer* ensureOutputLayer(std::optional<size_t> prevIndex,
                             const sp<LayerFE>& layerFE) {
      auto outputLayer = (prevIndex && *prevIndex <= mCurrentOutputLayersOrderedByZ.size())
              ? std::move(mCurrentOutputLayersOrderedByZ[*prevIndex])
              : BaseOutput::createOutputLayer(layerFE);
     auto result = outputLayer.get();
     mPendingOutputLayersOrderedByZ.emplace_back(std::move(outputLayer));
     return result;
}

rebuildLayerStacks先计算layer 是否可见,创建OutputLayer再计算脏区最后把可见layer 保存到一个容器中mCurrentOutputLayersOrderedByZ/mPendingOutputLayersOrderedByZ

frameworks/native/services/surfaceflinger/CompositionEngine/src/Display.cpp

  std::unique_ptr<compositionengine::OutputLayer> Display::createOutputLayer(
          const sp<compositionengine::LayerFE>& layerFE) const {
      auto result = impl::createOutputLayer(*this, layerFE);
  
      if (result && mId) {
          auto& hwc = getCompositionEngine().getHwComposer();
          auto displayId = *mId;
          // Note: For the moment we ensure it is safe to take a reference to the
          // HWComposer implementation by destroying all the OutputLayers (and
          // hence the HWC2::Layers they own) before setting a new HWComposer. See
          // for example SurfaceFlinger::updateVrFlinger().
          // TODO(b/121291683): Make this safer.
          auto hwcLayer = std::shared_ptr<HWC2::Layer>(hwc.createLayer(displayId),
                                                       [&hwc, displayId](HWC2::Layer* layer) {
                                                           hwc.destroyLayer(displayId, layer);
                                                       });
          ALOGE_IF(!hwcLayer, "Failed to create a HWC layer for a HWC supported display %s",
                   getName().c_str());
          result->setHwcLayer(std::move(hwcLayer));
      }
      return result;
  }

到现在为止计算出了待合成的layer ,封装为OutputLayer, 并创建了与之对应的hwc layer。继续看present逻辑:CompositionEngine::present

->Output::present

frameworks/native/services/surfaceflinger/CompositionEngine/src/Output.cpp

  void Output::present(const compositionengine::CompositionRefreshArgs& refreshArgs) {
      ATRACE_CALL();
      ALOGV(__FUNCTION__);
  
      updateColorProfile(refreshArgs);
      updateAndWriteCompositionState(refreshArgs);
      setColorTransform(refreshArgs);
      beginFrame();
      prepareFrame();//1
      devOptRepaintFlash(refreshArgs);
      finishFrame(refreshArgs);//2
      postFramebuffer();//3
  }
  • updateAndWriteCompositionState 通过 layer->writeStateToHWC, 再调用 Composer::setLayerBuffer将buffer传给底层,对应方法但是还没有真正显示
  • prepareFrame 选择合成策略 device /client,如果device 合成直接通过 Composer::presentOrValidateDisplay 显示,如果没有显示成功或者client合成继续走 hwcDisplay->validate逻辑
  • finishFrame 调用composeSurfaces 开始GPU处理layer 合成逻辑, GPU 合成后通过Composer::setClientTarget 将GPU合成后的buffer传给底层
  • postFramebuffer 如果存在client 合成再次调用 hwcDisplay->present送显

到此,SurfaceFlinger 中的Invalidate 和Refresh 消息主要工作就完成了,流程图如下:

20250910-110226.jpg

补充一点,SF dump中的hwc layer 就是打印的outputLayer

Display 0 HWC layers:
-----------------------------------------------------------------------------------------------------------------------------------------------
 Layer name
           Z |  Window Type |  Comp Type |  Transform |   Disp Frame (LTRB) |          Source Crop (LTRB) |     Frame Rate (Explicit) [Focused]
-----------------------------------------------------------------------------------------------------------------------------------------------
 com.theme.wallpaper.WallpaperService#0
  rel      0 |         2013 |     CLIENT |          0 |    0    0 2880 1080 |    0.0    0.0 2880.0 1080.0 |                              [ ]
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 com.android.launcher3/com.android.launcher3.Launcher#0
  rel      0 |            1 |     CLIENT |          0 |    0    0 2880 1080 |    0.0    0.0 2880.0 1080.0 |                              [ ]
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 #0
  rel      0 |         2038 |     CLIENT |          0 |    0    0 2880   96 |    0.0    0.0 2880.0   96.0 |                              [ ]
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 Background for -SurfaceView - dock#0
  rel     -1 |            0 |     CLIENT |          0 |  976  936 1904 1060 |    0.0    0.0    0.0    0.0 |                              [ ]
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
dock#0
  rel      0 |         2059 |     CLIENT |          0 |  976  920 1904 1080 |    0.0    0.0  928.0  160.0 |                              [ ]
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

从dump debug 可以判断layer 是否被可见性过滤掉了

frameworks/native/services/surfaceflinger/Layer.cpp

void Layer::miniDump(std::string& result, const DisplayDevice& display) const {
    const auto outputLayer = findOutputLayerForDisplay(&display);
    if (!outputLayer) {
        return;
    }
    std::string name;
    if (mName.length() > 77) {

5.3 实例分析

问题描述:地图应用由分屏到全屏时闪黑

我们先抓取perfetto 分析:

首先怀疑全屏尺寸没有设置到Layer,通过在Layer.cpp 中打log 发现全屏尺寸已经设置成功(1920):

2000-01-01 02:43:35.324   540   607 E Layer   : setSize  = SurfaceView - com.xxx.map.NaviActivity#0, 1920 

已经设置给layer了,那么就怀疑应用没有用新的尺寸绘制,我们先看trace 中setLayer 之后的应用端绘制:

设置完1920 后只画了两帧, 我们继续看下SF 端acquireBffer 有没有收到应用的绘制buffer,

从上面时间点后SF 一直没有收到SurfaceView 的buffer 更新,直到空调界面退出,大概 5、6s 后SF 终于收到SurfaceView 重绘的buffer.

也就证明了前面的猜想,窗口大小改变后应用确实没有重绘,通过打log 的方式也可以证明应用没有queueBuffer

//设置尺寸
2000-01-01 02:43:35.324   540   607 E Layer   : setSize  = SurfaceView - NaviActivity#0, 1920 
2000-01-01 02:43:35.324   540   607 E BufferQueueConsumer: [SurfaceView - NaviActivity#0](id:21c0000001a,api:0,p:-1,c:540) setDefaultBufferSize: width=1440 height=1920
//只有Activity 的queueBuffer 没有SurfaceView 的queueBuffer
2000-01-01 02:43:35.379   540  1115 E BufferQueueProducer: [NaviActivity#0](id:21c00000019,api:1,p:5204,c:540) queueBuffer: height=1920
2000-01-01 02:43:35.379   540  1115 E BufferQueueLayer: onFrameAvailable  = NaviActivity#0, 1920 
2000-01-01 02:43:35.408   540   540 E BufferLayerConsumer: updateTexImage  = NaviActivity#0, 1920 
2000-01-01 02:43:35.474   540   607 E BufferQueueProducer: [NaviActivity#0](id:21c00000019,api:1,p:5204,c:540) queueBuffer: height=1920
2000-01-01 02:43:35.474   540   607 E BufferQueueLayer: onFrameAvailable  = NaviActivity#0, 1920 
2000-01-01 02:43:35.541   540   540 E BufferLayerConsumer: updateTexImage  = NaviActivity#0, 1920 

//12 s 后SurfaceView 才queueBuffer
2000-01-01 02:43:47.125   540  2439 E BufferQueueProducer: [SurfaceView - NaviActivity#0](id:21c0000001a,api:1,p:5204,c:540) queueBuffer: height=1920

问题结论就是应用监听到大小变化要触发重绘。