/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// TODO(b/129481165): remove the #pragma below and fix conversion issues

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wconversion"

//#define LOG_NDEBUG 0
#undef LOG_TAG
#define LOG_TAG "Layer"
#define ATRACE_TAG ATRACE_TAG_GRAPHICS

#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <binder/IPCThreadState.h>
#include <common/trace.h>
#include <compositionengine/CompositionEngine.h>
#include <compositionengine/Display.h>
#include <compositionengine/LayerFECompositionState.h>
#include <compositionengine/OutputLayer.h>
#include <compositionengine/impl/OutputLayerCompositionState.h>
#include <cutils/compiler.h>
#include <cutils/native_handle.h>
#include <cutils/properties.h>
#include <ftl/enum.h>
#include <ftl/fake_guard.h>
#include <gui/BufferItem.h>
#include <gui/Surface.h>
#include <math.h>
#include <private/android_filesystem_config.h>
#include <renderengine/RenderEngine.h>
#include <stdint.h>
#include <stdlib.h>
#include <sys/types.h>
#include <system/graphics-base-v1.0.h>
#include <ui/DebugUtils.h>
#include <ui/FloatRect.h>
#include <ui/GraphicBuffer.h>
#include <ui/HdrRenderTypeUtils.h>
#include <ui/PixelFormat.h>
#include <ui/Rect.h>
#include <ui/Transform.h>
#include <utils/Errors.h>
#include <utils/Log.h>
#include <utils/NativeHandle.h>
#include <utils/StopWatch.h>

#include <algorithm>
#include <optional>

#include "DisplayDevice.h"
#include "DisplayHardware/HWComposer.h"
#include "FrameTimeline.h"
#include "FrameTracer/FrameTracer.h"
#include "FrontEnd/LayerCreationArgs.h"
#include "FrontEnd/LayerHandle.h"
#include "Layer.h"
#include "LayerProtoHelper.h"
#include "SurfaceFlinger.h"
#include "TimeStats/TimeStats.h"
#include "TransactionCallbackInvoker.h"
#include "TunnelModeEnabledReporter.h"
#include "Utils/FenceUtils.h"

#define DEBUG_RESIZE 0
#define EARLY_RELEASE_ENABLED false

namespace android {
using namespace std::chrono_literals;
namespace {
constexpr int kDumpTableRowLength = 159;

const ui::Transform kIdentityTransform;

TimeStats::SetFrameRateVote frameRateToSetFrameRateVotePayload(Layer::FrameRate frameRate) {
    using FrameRateCompatibility = TimeStats::SetFrameRateVote::FrameRateCompatibility;
    using Seamlessness = TimeStats::SetFrameRateVote::Seamlessness;
    const auto frameRateCompatibility = [frameRate] {
        switch (frameRate.vote.type) {
            case Layer::FrameRateCompatibility::Default:
                return FrameRateCompatibility::Default;
            case Layer::FrameRateCompatibility::ExactOrMultiple:
                return FrameRateCompatibility::ExactOrMultiple;
            default:
                return FrameRateCompatibility::Undefined;
        }
    }();

    const auto seamlessness = [frameRate] {
        switch (frameRate.vote.seamlessness) {
            case scheduler::Seamlessness::OnlySeamless:
                return Seamlessness::ShouldBeSeamless;
            case scheduler::Seamlessness::SeamedAndSeamless:
                return Seamlessness::NotRequired;
            default:
                return Seamlessness::Undefined;
        }
    }();

    return TimeStats::SetFrameRateVote{.frameRate = frameRate.vote.rate.getValue(),
                                       .frameRateCompatibility = frameRateCompatibility,
                                       .seamlessness = seamlessness};
}

} // namespace

using namespace ftl::flag_operators;

using base::StringAppendF;
using frontend::LayerSnapshot;
using frontend::RoundedCornerState;
using gui::GameMode;
using gui::LayerMetadata;
using gui::WindowInfo;
using ui::Size;

using PresentState = frametimeline::SurfaceFrame::PresentState;

Layer::Layer(const surfaceflinger::LayerCreationArgs& args)
      : sequence(args.sequence),
        mFlinger(sp<SurfaceFlinger>::fromExisting(args.flinger)),
        mName(base::StringPrintf("%s#%d", args.name.c_str(), sequence)),
        mWindowType(static_cast<WindowInfo::Type>(
                args.metadata.getInt32(gui::METADATA_WINDOW_TYPE, 0))) {
    ALOGV("Creating Layer %s", getDebugName());

    mDrawingState.crop = {0, 0, -1, -1};
    mDrawingState.sequence = 0;
    mDrawingState.transform.set(0, 0);
    mDrawingState.frameNumber = 0;
    mDrawingState.previousFrameNumber = 0;
    mDrawingState.barrierFrameNumber = 0;
    mDrawingState.producerId = 0;
    mDrawingState.barrierProducerId = 0;
    mDrawingState.bufferTransform = 0;
    mDrawingState.transformToDisplayInverse = false;
    mDrawingState.acquireFence = sp<Fence>::make(-1);
    mDrawingState.acquireFenceTime = std::make_shared<FenceTime>(mDrawingState.acquireFence);
    mDrawingState.dataspace = ui::Dataspace::V0_SRGB;
    mDrawingState.metadata = args.metadata;
    mDrawingState.frameTimelineInfo = {};
    mDrawingState.postTime = -1;
    mDeprecatedFrameTracker.setDisplayRefreshPeriod(
            args.flinger->mScheduler->getPacesetterVsyncPeriod().ns());

    mOwnerUid = args.ownerUid;
    mOwnerPid = args.ownerPid;
    mOwnerAppId = mOwnerUid % PER_USER_RANGE;

    mPotentialCursor = args.flags & ISurfaceComposerClient::eCursorWindow;
    mLayerFEs.emplace_back(frontend::LayerHierarchy::TraversalPath{static_cast<uint32_t>(sequence)},
                           args.flinger->getFactory().createLayerFE(mName, this));
}

void Layer::onFirstRef() {
    mFlinger->onLayerFirstRef(this);
}

Layer::~Layer() {
    LOG_ALWAYS_FATAL_IF(std::this_thread::get_id() != mFlinger->mMainThreadId,
                        "Layer destructor called off the main thread.");

    if (mBufferInfo.mBuffer != nullptr) {
        callReleaseBufferCallback(mDrawingState.releaseBufferListener,
                                  mBufferInfo.mBuffer->getBuffer(), mBufferInfo.mFrameNumber,
                                  mBufferInfo.mFence);
    }
    const int32_t layerId = getSequence();
    mFlinger->mTimeStats->onDestroy(layerId);
    mFlinger->mFrameTracer->onDestroy(layerId);

    mFlinger->onLayerDestroyed(this);

    const auto currentTime = std::chrono::steady_clock::now();
    if (mBufferInfo.mTimeSinceDataspaceUpdate > std::chrono::steady_clock::time_point::min()) {
        mFlinger->mLayerEvents.emplace_back(mOwnerUid, getSequence(), mBufferInfo.mDataspace,
                                            std::chrono::duration_cast<std::chrono::milliseconds>(
                                                    currentTime -
                                                    mBufferInfo.mTimeSinceDataspaceUpdate));
    }

    if (mDrawingState.sidebandStream != nullptr) {
        mFlinger->mTunnelModeEnabledReporter->decrementTunnelModeCount();
    }
    if (hasTrustedPresentationListener()) {
        mFlinger->mNumTrustedPresentationListeners--;
        updateTrustedPresentationState(nullptr, nullptr, -1 /* time_in_ms */, true /* leaveState*/);
    }
}

// ---------------------------------------------------------------------------
// set-up
// ---------------------------------------------------------------------------
sp<IBinder> Layer::getHandle() {
    Mutex::Autolock _l(mLock);
    if (mGetHandleCalled) {
        ALOGE("Get handle called twice" );
        return nullptr;
    }
    mGetHandleCalled = true;
    mHandleAlive = true;
    return sp<LayerHandle>::make(mFlinger, sp<Layer>::fromExisting(this));
}

// ---------------------------------------------------------------------------
// h/w composer set-up
// ---------------------------------------------------------------------------

// No early returns.
void Layer::updateTrustedPresentationState(const DisplayDevice* display,
                                           const frontend::LayerSnapshot* snapshot,
                                           int64_t time_in_ms, bool leaveState) {
    if (!hasTrustedPresentationListener()) {
        return;
    }
    const bool lastState = mLastComputedTrustedPresentationState;
    mLastComputedTrustedPresentationState = false;

    if (!leaveState) {
        const auto outputLayer = findOutputLayerForDisplay(display, snapshot->path);
        if (outputLayer != nullptr) {
            if (outputLayer->getState().coveredRegionExcludingDisplayOverlays) {
                Region coveredRegion =
                        *outputLayer->getState().coveredRegionExcludingDisplayOverlays;
                mLastComputedTrustedPresentationState =
                        computeTrustedPresentationState(snapshot->geomLayerBounds,
                                                        snapshot->sourceBounds(), coveredRegion,
                                                        snapshot->transformedBounds,
                                                        snapshot->alpha,
                                                        snapshot->geomLayerTransform,
                                                        mTrustedPresentationThresholds);
            } else {
                ALOGE("CoveredRegionExcludingDisplayOverlays was not set for %s. Don't compute "
                      "TrustedPresentationState",
                      getDebugName());
            }
        }
    }
    const bool newState = mLastComputedTrustedPresentationState;
    if (lastState && !newState) {
        // We were in the trusted presentation state, but now we left it,
        // emit the callback if needed
        if (mLastReportedTrustedPresentationState) {
            mLastReportedTrustedPresentationState = false;
            mTrustedPresentationListener.invoke(false);
        }
        // Reset the timer
        mEnteredTrustedPresentationStateTime = -1;
    } else if (!lastState && newState) {
        // We were not in the trusted presentation state, but we entered it, begin the timer
        // and make sure this gets called at least once more!
        mEnteredTrustedPresentationStateTime = time_in_ms;
        mFlinger->forceFutureUpdate(mTrustedPresentationThresholds.stabilityRequirementMs * 1.5);
    }

    // Has the timer elapsed, but we are still in the state? Emit a callback if needed
    if (!mLastReportedTrustedPresentationState && newState &&
        (time_in_ms - mEnteredTrustedPresentationStateTime >
         mTrustedPresentationThresholds.stabilityRequirementMs)) {
        mLastReportedTrustedPresentationState = true;
        mTrustedPresentationListener.invoke(true);
    }
}

/**
 * See SurfaceComposerClient.h: setTrustedPresentationCallback for discussion
 * of how the parameters and thresholds are interpreted. The general spirit is
 * to produce an upper bound on the amount of the buffer which was presented.
 */
bool Layer::computeTrustedPresentationState(const FloatRect& bounds, const FloatRect& sourceBounds,
                                            const Region& coveredRegion,
                                            const FloatRect& screenBounds, float alpha,
                                            const ui::Transform& effectiveTransform,
                                            const TrustedPresentationThresholds& thresholds) {
    if (alpha < thresholds.minAlpha) {
        return false;
    }
    if (sourceBounds.getWidth() == 0 || sourceBounds.getHeight() == 0) {
        return false;
    }
    if (screenBounds.getWidth() == 0 || screenBounds.getHeight() == 0) {
        return false;
    }

    const float sx = effectiveTransform.dsdx();
    const float sy = effectiveTransform.dsdy();
    float fractionRendered = std::min(sx * sy, 1.0f);

    float boundsOverSourceW = bounds.getWidth() / (float)sourceBounds.getWidth();
    float boundsOverSourceH = bounds.getHeight() / (float)sourceBounds.getHeight();
    fractionRendered *= boundsOverSourceW * boundsOverSourceH;

    Region tJunctionFreeRegion = Region::createTJunctionFreeRegion(coveredRegion);
    // Compute the size of all the rects since they may be disconnected.
    float coveredSize = 0;
    for (auto rect = tJunctionFreeRegion.begin(); rect < tJunctionFreeRegion.end(); rect++) {
        float size = rect->width() * rect->height();
        coveredSize += size;
    }

    fractionRendered *= (1 - (coveredSize / (screenBounds.getWidth() * screenBounds.getHeight())));

    if (fractionRendered < thresholds.minFractionRendered) {
        return false;
    }

    return true;
}

Rect Layer::getCroppedBufferSize(const State& s) const {
    Rect size = getBufferSize(s);
    Rect crop = Rect(getCrop(s));
    if (!crop.isEmpty() && size.isValid()) {
        size.intersect(crop, &size);
    } else if (!crop.isEmpty()) {
        size = crop;
    }
    return size;
}

const char* Layer::getDebugName() const {
    return mName.c_str();
}

// ---------------------------------------------------------------------------
// drawing...
// ---------------------------------------------------------------------------

aidl::android::hardware::graphics::composer3::Composition Layer::getCompositionType(
        const DisplayDevice& display) const {
    const auto outputLayer = findOutputLayerForDisplay(&display);
    return getCompositionType(outputLayer);
}

aidl::android::hardware::graphics::composer3::Composition Layer::getCompositionType(
        const compositionengine::OutputLayer* outputLayer) const {
    if (outputLayer == nullptr) {
        return aidl::android::hardware::graphics::composer3::Composition::INVALID;
    }
    if (outputLayer->getState().hwc) {
        return (*outputLayer->getState().hwc).hwcCompositionType;
    } else {
        return aidl::android::hardware::graphics::composer3::Composition::CLIENT;
    }
}

// ----------------------------------------------------------------------------
// transaction
// ----------------------------------------------------------------------------

void Layer::commitTransaction() {
    // Set the present state for all bufferlessSurfaceFramesTX to Presented. The
    // bufferSurfaceFrameTX will be presented in latchBuffer.
    for (auto& [token, surfaceFrame] : mDrawingState.bufferlessSurfaceFramesTX) {
        if (surfaceFrame->getPresentState() != PresentState::Presented) {
            // With applyPendingStates, we could end up having presented surfaceframes from previous
            // states
            surfaceFrame->setPresentState(PresentState::Presented, mLastLatchTime);
            mFlinger->mFrameTimeline->addSurfaceFrame(surfaceFrame);
        }
    }
    mDrawingState.bufferlessSurfaceFramesTX.clear();
}

void Layer::setTransactionFlags(uint32_t mask) {
    mTransactionFlags |= mask;
}

bool Layer::setCrop(const FloatRect& crop) {
    if (mDrawingState.crop == crop) return false;
    mDrawingState.sequence++;
    mDrawingState.crop = crop;

    setTransactionFlags(eTransactionNeeded);
    return true;
}

bool Layer::isLayerFocusedBasedOnPriority(int32_t priority) {
    return priority == PRIORITY_FOCUSED_WITH_MODE || priority == PRIORITY_FOCUSED_WITHOUT_MODE;
};

void Layer::setFrameTimelineVsyncForBufferTransaction(const FrameTimelineInfo& info,
                                                      nsecs_t postTime, gui::GameMode gameMode) {
    mDrawingState.postTime = postTime;

    // Check if one of the bufferlessSurfaceFramesTX contains the same vsyncId. This can happen if
    // there are two transactions with the same token, the first one without a buffer and the
    // second one with a buffer. We promote the bufferlessSurfaceFrame to a bufferSurfaceFrameTX
    // in that case.
    auto it = mDrawingState.bufferlessSurfaceFramesTX.find(info.vsyncId);
    if (it != mDrawingState.bufferlessSurfaceFramesTX.end()) {
        // Promote the bufferlessSurfaceFrame to a bufferSurfaceFrameTX
        mDrawingState.bufferSurfaceFrameTX = it->second;
        mDrawingState.bufferlessSurfaceFramesTX.erase(it);
        mDrawingState.bufferSurfaceFrameTX->promoteToBuffer();
        mDrawingState.bufferSurfaceFrameTX->setActualQueueTime(postTime);
    } else {
        mDrawingState.bufferSurfaceFrameTX =
                createSurfaceFrameForBuffer(info, postTime, mTransactionName, gameMode);
    }

    setFrameTimelineVsyncForSkippedFrames(info, postTime, mTransactionName, gameMode);
}

void Layer::setFrameTimelineVsyncForBufferlessTransaction(const FrameTimelineInfo& info,
                                                          nsecs_t postTime,
                                                          gui::GameMode gameMode) {
    mDrawingState.frameTimelineInfo = info;
    mDrawingState.postTime = postTime;
    setTransactionFlags(eTransactionNeeded);

    if (const auto& bufferSurfaceFrameTX = mDrawingState.bufferSurfaceFrameTX;
        bufferSurfaceFrameTX != nullptr) {
        if (bufferSurfaceFrameTX->getToken() == info.vsyncId) {
            // BufferSurfaceFrame takes precedence over BufferlessSurfaceFrame. If the same token is
            // being used for BufferSurfaceFrame, don't create a new one.
            return;
        }
    }
    // For Transactions without a buffer, we create only one SurfaceFrame per vsyncId. If multiple
    // transactions use the same vsyncId, we just treat them as one SurfaceFrame (unless they are
    // targeting different vsyncs).
    auto it = mDrawingState.bufferlessSurfaceFramesTX.find(info.vsyncId);
    if (it == mDrawingState.bufferlessSurfaceFramesTX.end()) {
        auto surfaceFrame = createSurfaceFrameForTransaction(info, postTime, gameMode);
        mDrawingState.bufferlessSurfaceFramesTX[info.vsyncId] = surfaceFrame;
    } else {
        if (it->second->getPresentState() == PresentState::Presented) {
            // If the SurfaceFrame was already presented, its safe to overwrite it since it must
            // have been from previous vsync.
            it->second = createSurfaceFrameForTransaction(info, postTime, gameMode);
        }
    }

    setFrameTimelineVsyncForSkippedFrames(info, postTime, mTransactionName, gameMode);
}

void Layer::addSurfaceFrameDroppedForBuffer(
        std::shared_ptr<frametimeline::SurfaceFrame>& surfaceFrame, nsecs_t dropTime) {
    surfaceFrame->setDropTime(dropTime);
    surfaceFrame->setPresentState(PresentState::Dropped);
    mFlinger->mFrameTimeline->addSurfaceFrame(surfaceFrame);
}

void Layer::addSurfaceFramePresentedForBuffer(
        std::shared_ptr<frametimeline::SurfaceFrame>& surfaceFrame, nsecs_t acquireFenceTime,
        nsecs_t currentLatchTime) {
    surfaceFrame->setAcquireFenceTime(acquireFenceTime);
    surfaceFrame->setPresentState(PresentState::Presented, mLastLatchTime);
    mFlinger->mFrameTimeline->addSurfaceFrame(surfaceFrame);
    updateLastLatchTime(currentLatchTime);
}

std::shared_ptr<frametimeline::SurfaceFrame> Layer::createSurfaceFrameForTransaction(
        const FrameTimelineInfo& info, nsecs_t postTime, gui::GameMode gameMode) {
    auto surfaceFrame =
            mFlinger->mFrameTimeline->createSurfaceFrameForToken(info, mOwnerPid, mOwnerUid,
                                                                 getSequence(), mName,
                                                                 mTransactionName,
                                                                 /*isBuffer*/ false, gameMode);
    // Buffer hasn't yet been latched, so use mDrawingState
    surfaceFrame->setDesiredPresentTime(mDrawingState.desiredPresentTime);

    surfaceFrame->setActualStartTime(info.startTimeNanos);
    // For Transactions, the post time is considered to be both queue and acquire fence time.
    surfaceFrame->setActualQueueTime(postTime);
    surfaceFrame->setAcquireFenceTime(postTime);
    const auto fps = mFlinger->mScheduler->getFrameRateOverride(getOwnerUid());
    if (fps) {
        surfaceFrame->setRenderRate(*fps);
    }
    return surfaceFrame;
}

std::shared_ptr<frametimeline::SurfaceFrame> Layer::createSurfaceFrameForBuffer(
        const FrameTimelineInfo& info, nsecs_t queueTime, std::string debugName,
        gui::GameMode gameMode) {
    auto surfaceFrame =
            mFlinger->mFrameTimeline->createSurfaceFrameForToken(info, mOwnerPid, mOwnerUid,
                                                                 getSequence(), mName, debugName,
                                                                 /*isBuffer*/ true, gameMode);
    // Buffer hasn't yet been latched, so use mDrawingState
    surfaceFrame->setDesiredPresentTime(mDrawingState.desiredPresentTime);
    surfaceFrame->setActualStartTime(info.startTimeNanos);
    // For buffers, acquire fence time will set during latch.
    surfaceFrame->setActualQueueTime(queueTime);
    const auto fps = mFlinger->mScheduler->getFrameRateOverride(getOwnerUid());
    if (fps) {
        surfaceFrame->setRenderRate(*fps);
    }
    return surfaceFrame;
}

void Layer::setFrameTimelineVsyncForSkippedFrames(const FrameTimelineInfo& info, nsecs_t postTime,
                                                  std::string debugName, gui::GameMode gameMode) {
    if (info.skippedFrameVsyncId == FrameTimelineInfo::INVALID_VSYNC_ID) {
        return;
    }

    FrameTimelineInfo skippedFrameTimelineInfo = info;
    skippedFrameTimelineInfo.vsyncId = info.skippedFrameVsyncId;

    auto surfaceFrame =
            mFlinger->mFrameTimeline->createSurfaceFrameForToken(skippedFrameTimelineInfo,
                                                                 mOwnerPid, mOwnerUid,
                                                                 getSequence(), mName, debugName,
                                                                 /*isBuffer*/ false, gameMode);
    // Buffer hasn't yet been latched, so use mDrawingState
    surfaceFrame->setDesiredPresentTime(mDrawingState.desiredPresentTime);
    surfaceFrame->setActualStartTime(skippedFrameTimelineInfo.skippedFrameStartTimeNanos);
    // For Transactions, the post time is considered to be both queue and acquire fence time.
    surfaceFrame->setActualQueueTime(postTime);
    surfaceFrame->setAcquireFenceTime(postTime);
    const auto fps = mFlinger->mScheduler->getFrameRateOverride(getOwnerUid());
    if (fps) {
        surfaceFrame->setRenderRate(*fps);
    }
    addSurfaceFrameDroppedForBuffer(surfaceFrame, postTime);
}

bool Layer::setFrameRateForLayerTree(FrameRate frameRate, const scheduler::LayerProps& layerProps,
                                     nsecs_t now) {
    if (mDrawingState.frameRateForLayerTree == frameRate) {
        return false;
    }

    mDrawingState.frameRateForLayerTree = frameRate;
    mFlinger->mScheduler
            ->recordLayerHistory(sequence, layerProps, now, now,
                                 scheduler::LayerHistory::LayerUpdateType::SetFrameRate);
    return true;
}

Layer::FrameRate Layer::getFrameRateForLayerTree() const {
    return getDrawingState().frameRateForLayerTree;
}

// ----------------------------------------------------------------------------
// debugging
// ----------------------------------------------------------------------------

void Layer::miniDumpHeader(std::string& result) {
    result.append(kDumpTableRowLength, '-');
    result.append("\n");
    result.append(" Layer name\n");
    result.append("           Z | ");
    result.append(" Window Type | ");
    result.append(" Comp Type | ");
    result.append(" Transform | ");
    result.append("  Disp Frame (LTRB) | ");
    result.append("         Source Crop (LTRB) | ");
    result.append("    Frame Rate (Explicit) (Seamlessness) [Focused]\n");
    result.append(kDumpTableRowLength, '-');
    result.append("\n");
}

void Layer::miniDump(std::string& result, const frontend::LayerSnapshot& snapshot,
                     const DisplayDevice& display) const {
    const auto outputLayer = findOutputLayerForDisplay(&display, snapshot.path);
    if (!outputLayer) {
        return;
    }

    StringAppendF(&result, " %s\n", snapshot.debugName.c_str());
    StringAppendF(&result, "  %10zu | ", snapshot.globalZ);
    StringAppendF(&result, "  %10d | ",
                  snapshot.layerMetadata.getInt32(gui::METADATA_WINDOW_TYPE, 0));
    StringAppendF(&result, "%10s | ", toString(getCompositionType(outputLayer)).c_str());
    const auto& outputLayerState = outputLayer->getState();
    StringAppendF(&result, "%10s | ", toString(outputLayerState.bufferTransform).c_str());
    const Rect& frame = outputLayerState.displayFrame;
    StringAppendF(&result, "%4d %4d %4d %4d | ", frame.left, frame.top, frame.right, frame.bottom);
    const FloatRect& crop = outputLayerState.sourceCrop;
    StringAppendF(&result, "%6.1f %6.1f %6.1f %6.1f | ", crop.left, crop.top, crop.right,
                  crop.bottom);
    const auto frameRate = snapshot.frameRate;
    std::string frameRateStr;
    if (frameRate.vote.rate.isValid()) {
        StringAppendF(&frameRateStr, "%.2f", frameRate.vote.rate.getValue());
    }
    if (frameRate.vote.rate.isValid() || frameRate.vote.type != FrameRateCompatibility::Default) {
        StringAppendF(&result, "%6s %15s %17s", frameRateStr.c_str(),
                      ftl::enum_string(frameRate.vote.type).c_str(),
                      ftl::enum_string(frameRate.vote.seamlessness).c_str());
    } else if (frameRate.category != FrameRateCategory::Default) {
        StringAppendF(&result, "%6s %15s %17s", frameRateStr.c_str(),
                      (std::string("Cat::") + ftl::enum_string(frameRate.category)).c_str(),
                      ftl::enum_string(frameRate.vote.seamlessness).c_str());
    } else {
        result.append(41, ' ');
    }

    const auto focused = isLayerFocusedBasedOnPriority(snapshot.frameRateSelectionPriority);
    StringAppendF(&result, "    [%s]\n", focused ? "*" : " ");

    result.append(kDumpTableRowLength, '-');
    result.append("\n");
}

void Layer::dumpFrameStats(std::string& result) const {
    if (FlagManager::getInstance().deprecate_frame_tracker()) {
        FrameStats fs = FrameStats();
        getFrameStats(&fs);
        for (auto desired = fs.desiredPresentTimesNano.begin(),
                  actual = fs.actualPresentTimesNano.begin(),
                  ready = fs.frameReadyTimesNano.begin();
             desired != fs.desiredPresentTimesNano.end() &&
             actual != fs.actualPresentTimesNano.end() && ready != fs.frameReadyTimesNano.end();
             ++desired, ++actual, ++ready) {
            result.append(std::format("{}\t{}\t{}\n", *desired, *actual, *ready));
        }

        result.push_back('\n');
    } else {
        mDeprecatedFrameTracker.dumpStats(result);
    }
}

void Layer::clearFrameStats() {
    if (FlagManager::getInstance().deprecate_frame_tracker()) {
        mFrameStatsHistorySize = 0;
    } else {
        mDeprecatedFrameTracker.clearStats();
    }
}

void Layer::getFrameStats(FrameStats* outStats) const {
    if (FlagManager::getInstance().deprecate_frame_tracker()) {
        if (auto ftl = getTimeline()) {
            float fps = ftl->get().computeFps({getSequence()});
            ftl->get().generateFrameStats(getSequence(), mFrameStatsHistorySize, outStats);
            outStats->refreshPeriodNano = Fps::fromValue(fps).getPeriodNsecs();
        }
    } else {
        mDeprecatedFrameTracker.getStats(outStats);
    }
}

void Layer::onDisconnect() {
    const int32_t layerId = getSequence();
    mFlinger->mTimeStats->onDestroy(layerId);
    mFlinger->mFrameTracer->onDestroy(layerId);
}

void Layer::writeCompositionStateToProto(perfetto::protos::LayerProto* layerProto,
                                         ui::LayerStack layerStack) {
    ftl::FakeGuard guard(mFlinger->mStateLock); // Called from the main thread.
    ftl::FakeGuard mainThreadGuard(kMainThreadContext);

    // Only populate for the primary display.
    if (const auto display = mFlinger->getDisplayFromLayerStack(layerStack)) {
        const auto compositionType = getCompositionType(*display);
        layerProto->set_hwc_composition_type(
                static_cast<perfetto::protos::HwcCompositionType>(compositionType));
        LayerProtoHelper::writeToProto(getVisibleRegion(display),
                                       [&]() { return layerProto->mutable_visible_region(); });
    }
}

compositionengine::OutputLayer* Layer::findOutputLayerForDisplay(
        const DisplayDevice* display) const {
    if (!display) return nullptr;
    sp<LayerFE> layerFE;
    frontend::LayerHierarchy::TraversalPath path{.id = static_cast<uint32_t>(sequence)};
    for (auto& [p, layer] : mLayerFEs) {
        if (p == path) {
            layerFE = layer;
        }
    }

    if (!layerFE) return nullptr;
    return display->getCompositionDisplay()->getOutputLayerForLayer(layerFE);
}

compositionengine::OutputLayer* Layer::findOutputLayerForDisplay(
        const DisplayDevice* display, const frontend::LayerHierarchy::TraversalPath& path) const {
    if (!display) return nullptr;
    sp<LayerFE> layerFE;
    for (auto& [p, layer] : mLayerFEs) {
        if (p == path) {
            layerFE = layer;
        }
    }

    if (!layerFE) return nullptr;
    return display->getCompositionDisplay()->getOutputLayerForLayer(layerFE);
}

Region Layer::getVisibleRegion(const DisplayDevice* display) const {
    const auto outputLayer = findOutputLayerForDisplay(display);
    return outputLayer ? outputLayer->getState().visibleRegion : Region();
}

void Layer::callReleaseBufferCallback(const sp<ITransactionCompletedListener>& listener,
                                      const sp<GraphicBuffer>& buffer, uint64_t framenumber,
                                      const sp<Fence>& releaseFence) {
    if (!listener && !mBufferReleaseChannel) {
        return;
    }

    SFTRACE_FORMAT_INSTANT("callReleaseBufferCallback %s - %" PRIu64, getDebugName(), framenumber);

    ReleaseCallbackId callbackId{buffer->getId(), framenumber};
    const sp<Fence>& fence = releaseFence ? releaseFence : Fence::NO_FENCE;
    uint32_t currentMaxAcquiredBufferCount =
            mFlinger->getMaxAcquiredBufferCountForCurrentRefreshRate(mOwnerUid);

    if (listener) {
        listener->onReleaseBuffer(callbackId, fence, currentMaxAcquiredBufferCount);
    }

    if (!mBufferReleaseChannel) {
        return;
    }

    status_t status = mBufferReleaseChannel->writeReleaseFence(callbackId, fence,
                                                               currentMaxAcquiredBufferCount);
    if (status != OK) {
        int error = -status;
        // callReleaseBufferCallback is called during Layer's destructor. In this case, it's
        // expected to receive connection errors.
        if (error != EPIPE && error != ECONNRESET) {
            ALOGD("[%s] writeReleaseFence failed. error %d (%s)", getDebugName(), error,
                  strerror(error));
        }
    }
}

sp<CallbackHandle> Layer::findCallbackHandle() {
    // If we are displayed on multiple displays in a single composition cycle then we would
    // need to do careful tracking to enable the use of the mLastClientCompositionFence.
    //  For example we can only use it if all the displays are client comp, and we need
    //  to merge all the client comp fences. We could do this, but for now we just
    // disable the optimization when a layer is composed on multiple displays.
    if (mClearClientCompositionFenceOnLayerDisplayed) {
        mLastClientCompositionFence = nullptr;
    } else {
        mClearClientCompositionFenceOnLayerDisplayed = true;
    }

    // The previous release fence notifies the client that SurfaceFlinger is done with the previous
    // buffer that was presented on this layer. The first transaction that came in this frame that
    // replaced the previous buffer on this layer needs this release fence, because the fence will
    // let the client know when that previous buffer is removed from the screen.
    //
    // Every other transaction on this layer does not need a release fence because no other
    // Transactions that were set on this layer this frame are going to have their preceding buffer
    // removed from the display this frame.
    //
    // For example, if we have 3 transactions this frame. The first transaction doesn't contain a
    // buffer so it doesn't need a previous release fence because the layer still needs the previous
    // buffer. The second transaction contains a buffer so it needs a previous release fence because
    // the previous buffer will be released this frame. The third transaction also contains a
    // buffer. It replaces the buffer in the second transaction. The buffer in the second
    // transaction will now no longer be presented so it is released immediately and the third
    // transaction doesn't need a previous release fence.
    sp<CallbackHandle> ch;
    for (auto& handle : mDrawingState.callbackHandles) {
        if (handle->releasePreviousBuffer && mPreviousReleaseBufferEndpoint == handle->listener) {
            ch = handle;
            break;
        }
    }
    return ch;
}

void Layer::prepareReleaseCallbacks(ftl::Future<FenceResult> futureFenceResult,
                                    ui::LayerStack layerStack) {
    sp<CallbackHandle> ch = findCallbackHandle();

    if (ch != nullptr) {
        ch->previousReleaseCallbackId = mPreviousReleaseCallbackId;
        ch->previousReleaseFences.emplace_back(std::move(futureFenceResult));
        ch->name = mName;
    } else {
        // If we didn't get a release callback yet (e.g. some scenarios when capturing
        // screenshots asynchronously) then make sure we don't drop the fence.
        // Older fences for the same layer stack can be dropped when a new fence arrives.
        // An assumption here is that RenderEngine performs work sequentially, so an
        // incoming fence will not fire before an existing fence.
        mAdditionalPreviousReleaseFences.emplace_or_replace(layerStack,
                                                            std::move(futureFenceResult));
    }

    if (mBufferInfo.mBuffer) {
        mPreviouslyPresentedLayerStacks.push_back(layerStack);
    }

    if (mDrawingState.frameNumber > 0) {
        mDrawingState.previousFrameNumber = mDrawingState.frameNumber;
    }
}

void Layer::releasePendingBuffer(nsecs_t dequeueReadyTime) {
    for (const auto& handle : mDrawingState.callbackHandles) {
        handle->bufferReleaseChannel = mBufferReleaseChannel;
        handle->transformHint = mTransformHint;
        handle->dequeueReadyTime = dequeueReadyTime;
        handle->currentMaxAcquiredBufferCount =
                mFlinger->getMaxAcquiredBufferCountForCurrentRefreshRate(mOwnerUid);
        SFTRACE_FORMAT_INSTANT("releasePendingBuffer %s - %" PRIu64, getDebugName(),
                               handle->previousReleaseCallbackId.framenumber);
    }

    for (auto& handle : mDrawingState.callbackHandles) {
        if (handle->releasePreviousBuffer && mPreviousReleaseBufferEndpoint == handle->listener) {
            handle->previousReleaseCallbackId = mPreviousReleaseCallbackId;
            break;
        }
    }

    mFlinger->getTransactionCallbackInvoker().addCallbackHandles(mDrawingState.callbackHandles);
    mDrawingState.callbackHandles = {};
}

bool Layer::setTransform(uint32_t transform) {
    if (mDrawingState.bufferTransform == transform) return false;
    mDrawingState.bufferTransform = transform;
    setTransactionFlags(eTransactionNeeded);
    return true;
}

bool Layer::setTransformToDisplayInverse(bool transformToDisplayInverse) {
    if (mDrawingState.transformToDisplayInverse == transformToDisplayInverse) return false;
    mDrawingState.sequence++;
    mDrawingState.transformToDisplayInverse = transformToDisplayInverse;
    setTransactionFlags(eTransactionNeeded);
    return true;
}

void Layer::releasePreviousBuffer() {
    mReleasePreviousBuffer = true;
    if (!mBufferInfo.mBuffer ||
        (!mDrawingState.buffer->hasSameBuffer(*mBufferInfo.mBuffer) ||
         mDrawingState.frameNumber != mBufferInfo.mFrameNumber)) {
        // If mDrawingState has a buffer, and we are about to update again
        // before swapping to drawing state, then the first buffer will be
        // dropped and we should decrement the pending buffer count and
        // call any release buffer callbacks if set.
        callReleaseBufferCallback(mDrawingState.releaseBufferListener,
                                  mDrawingState.buffer->getBuffer(), mDrawingState.frameNumber,
                                  mDrawingState.acquireFence);
        const int32_t layerId = getSequence();
        mFlinger->mTimeStats->removeTimeRecord(layerId, mDrawingState.frameNumber);
        decrementPendingBufferCount();
        if (mDrawingState.bufferSurfaceFrameTX != nullptr &&
            mDrawingState.bufferSurfaceFrameTX->getPresentState() != PresentState::Presented) {
            addSurfaceFrameDroppedForBuffer(mDrawingState.bufferSurfaceFrameTX, systemTime());
            mDrawingState.bufferSurfaceFrameTX.reset();
        }
    } else if (EARLY_RELEASE_ENABLED && mLastClientCompositionFence != nullptr) {
        callReleaseBufferCallback(mDrawingState.releaseBufferListener,
                                  mDrawingState.buffer->getBuffer(), mDrawingState.frameNumber,
                                  mLastClientCompositionFence);
        mLastClientCompositionFence = nullptr;
    }
}

void Layer::resetDrawingStateBufferInfo() {
    mDrawingState.producerId = 0;
    mDrawingState.frameNumber = 0;
    mDrawingState.previousFrameNumber = 0;
    mDrawingState.releaseBufferListener = nullptr;
    mDrawingState.buffer = nullptr;
    mDrawingState.acquireFence = sp<Fence>::make(-1);
    mDrawingState.acquireFenceTime = std::make_unique<FenceTime>(mDrawingState.acquireFence);
    mCallbackHandleAcquireTimeOrFence = mDrawingState.acquireFenceTime->getSignalTime();
    mDrawingState.releaseBufferEndpoint = nullptr;
}

bool Layer::setBuffer(std::shared_ptr<renderengine::ExternalTexture>& buffer,
                      const BufferData& bufferData, nsecs_t postTime, nsecs_t desiredPresentTime,
                      bool isAutoTimestamp, const FrameTimelineInfo& info, gui::GameMode gameMode) {
    SFTRACE_FORMAT("setBuffer %s - hasBuffer=%s", getDebugName(), (buffer ? "true" : "false"));

    const bool frameNumberChanged =
            bufferData.flags.test(BufferData::BufferDataChange::frameNumberChanged);
    const uint64_t frameNumber =
            frameNumberChanged ? bufferData.frameNumber : mDrawingState.frameNumber + 1;
    SFTRACE_FORMAT_INSTANT("setBuffer %s - %" PRIu64, getDebugName(), frameNumber);

    if (mDrawingState.buffer) {
        releasePreviousBuffer();
    } else if (buffer) {
        // if we are latching a buffer for the first time then clear the mLastLatchTime since
        // we don't want to incorrectly classify a frame if we miss the desired present time.
        updateLastLatchTime(0);
    }

    mDrawingState.desiredPresentTime = desiredPresentTime;
    mDrawingState.isAutoTimestamp = isAutoTimestamp;
    mDrawingState.latchedVsyncId = info.vsyncId;
    mDrawingState.useVsyncIdForRefreshRateSelection = info.useForRefreshRateSelection;
    if (!buffer) {
        resetDrawingStateBufferInfo();
        setTransactionFlags(eTransactionNeeded);
        mDrawingState.bufferSurfaceFrameTX = nullptr;
        setFrameTimelineVsyncForBufferlessTransaction(info, postTime, gameMode);
        return true;
    } else {
        // release sideband stream if it exists and a non null buffer is being set
        if (mDrawingState.sidebandStream != nullptr) {
            setSidebandStream(nullptr, info, postTime, gameMode);
        }
    }

    if ((mDrawingState.producerId > bufferData.producerId) ||
        ((mDrawingState.producerId == bufferData.producerId) &&
         (mDrawingState.frameNumber > frameNumber))) {
        ALOGE("Out of order buffers detected for %s producedId=%d frameNumber=%" PRIu64
              " -> producedId=%d frameNumber=%" PRIu64,
              getDebugName(), mDrawingState.producerId, mDrawingState.frameNumber,
              bufferData.producerId, frameNumber);
        TransactionTraceWriter::getInstance().invoke("out_of_order_buffers_", /*overwrite=*/false);
    }

    mDrawingState.producerId = bufferData.producerId;
    mDrawingState.barrierProducerId =
            std::max(mDrawingState.producerId, mDrawingState.barrierProducerId);
    mDrawingState.frameNumber = frameNumber;
    mDrawingState.barrierFrameNumber =
            std::max(mDrawingState.frameNumber, mDrawingState.barrierFrameNumber);

    mDrawingState.releaseBufferListener = bufferData.releaseBufferListener;
    mDrawingState.buffer = std::move(buffer);
    mDrawingState.acquireFence = bufferData.flags.test(BufferData::BufferDataChange::fenceChanged)
            ? bufferData.acquireFence
            : Fence::NO_FENCE;
    mDrawingState.acquireFenceTime = std::make_unique<FenceTime>(mDrawingState.acquireFence);
    if (mDrawingState.acquireFenceTime->getSignalTime() == Fence::SIGNAL_TIME_PENDING) {
        // We latched this buffer unsiganled, so we need to pass the acquire fence
        // on the callback instead of just the acquire time, since it's unknown at
        // this point.
        mCallbackHandleAcquireTimeOrFence = mDrawingState.acquireFence;
    } else {
        mCallbackHandleAcquireTimeOrFence = mDrawingState.acquireFenceTime->getSignalTime();
    }
    setTransactionFlags(eTransactionNeeded);

    const int32_t layerId = getSequence();
    mFlinger->mTimeStats->setPostTime(layerId, mDrawingState.frameNumber, getName().c_str(),
                                      mOwnerUid, postTime, gameMode);

    setFrameTimelineVsyncForBufferTransaction(info, postTime, gameMode);

    if (bufferData.dequeueTime > 0) {
        const uint64_t bufferId = mDrawingState.buffer->getId();
        mFlinger->mFrameTracer->traceNewLayer(layerId, getName().c_str());
        mFlinger->mFrameTracer->traceTimestamp(layerId, bufferId, frameNumber,
                                               bufferData.dequeueTime,
                                               FrameTracer::FrameEvent::DEQUEUE);
        mFlinger->mFrameTracer->traceTimestamp(layerId, bufferId, frameNumber, postTime,
                                               FrameTracer::FrameEvent::QUEUE);
    }

    mDrawingState.releaseBufferEndpoint = bufferData.releaseBufferEndpoint;

    // If the layer had been updated a TextureView, this would make sure the present time could be
    // same to TextureView update when it's a small dirty, and get the correct heuristic rate.
    if (mFlinger->mScheduler->supportSmallDirtyDetection(mOwnerAppId)) {
        if (mDrawingState.useVsyncIdForRefreshRateSelection) {
            mUsedVsyncIdForRefreshRateSelection = true;
        }
    }
    return true;
}

void Layer::setDesiredPresentTime(nsecs_t desiredPresentTime, bool isAutoTimestamp) {
    mDrawingState.desiredPresentTime = desiredPresentTime;
    mDrawingState.isAutoTimestamp = isAutoTimestamp;
}

void Layer::recordLayerHistoryBufferUpdate(const scheduler::LayerProps& layerProps, nsecs_t now) {
    SFTRACE_CALL();
    const nsecs_t presentTime = [&] {
        if (!mDrawingState.isAutoTimestamp) {
            SFTRACE_FORMAT_INSTANT("desiredPresentTime");
            return mDrawingState.desiredPresentTime;
        }

        if (mDrawingState.useVsyncIdForRefreshRateSelection) {
            const auto prediction =
                    mFlinger->mFrameTimeline->getTokenManager()->getPredictionsForToken(
                            mDrawingState.latchedVsyncId);
            if (prediction.has_value()) {
                SFTRACE_FORMAT_INSTANT("predictedPresentTime");
                mMaxTimeForUseVsyncId = prediction->presentTime +
                        scheduler::LayerHistory::kMaxPeriodForHistory.count();
                return prediction->presentTime;
            }
        }

        if (!mFlinger->mScheduler->supportSmallDirtyDetection(mOwnerAppId)) {
            return static_cast<nsecs_t>(0);
        }

        // If the layer is not an application and didn't set an explicit rate or desiredPresentTime,
        // return "0" to tell the layer history that it will use the max refresh rate without
        // calculating the adaptive rate.
        if (mWindowType != WindowInfo::Type::APPLICATION &&
            mWindowType != WindowInfo::Type::BASE_APPLICATION) {
            return static_cast<nsecs_t>(0);
        }

        // Return the valid present time only when the layer potentially updated a TextureView so
        // LayerHistory could heuristically calculate the rate if the UI is continually updating.
        if (mUsedVsyncIdForRefreshRateSelection) {
            const auto prediction =
                    mFlinger->mFrameTimeline->getTokenManager()->getPredictionsForToken(
                            mDrawingState.latchedVsyncId);
            if (prediction.has_value()) {
                if (mMaxTimeForUseVsyncId >= prediction->presentTime) {
                    return prediction->presentTime;
                }
                mUsedVsyncIdForRefreshRateSelection = false;
            }
        }

        return static_cast<nsecs_t>(0);
    }();

    if (SFTRACE_ENABLED() && presentTime > 0) {
        const auto presentIn = TimePoint::fromNs(presentTime) - TimePoint::now();
        SFTRACE_FORMAT_INSTANT("presentIn %s", to_string(presentIn).c_str());
    }

    mFlinger->mScheduler->recordLayerHistory(sequence, layerProps, presentTime, now,
                                             scheduler::LayerHistory::LayerUpdateType::Buffer);
}

void Layer::recordLayerHistoryAnimationTx(const scheduler::LayerProps& layerProps, nsecs_t now) {
    const nsecs_t presentTime =
            mDrawingState.isAutoTimestamp ? 0 : mDrawingState.desiredPresentTime;
    mFlinger->mScheduler->recordLayerHistory(sequence, layerProps, presentTime, now,
                                             scheduler::LayerHistory::LayerUpdateType::AnimationTX);
}

bool Layer::setDataspace(ui::Dataspace dataspace) {
    if (mDrawingState.dataspace == dataspace) return false;
    mDrawingState.dataspace = dataspace;
    setTransactionFlags(eTransactionNeeded);
    return true;
}

bool Layer::setExtendedRangeBrightness(float currentBufferRatio, float desiredRatio) {
    if (mDrawingState.currentHdrSdrRatio == currentBufferRatio &&
        mDrawingState.desiredHdrSdrRatio == desiredRatio)
        return false;
    mDrawingState.currentHdrSdrRatio = currentBufferRatio;
    mDrawingState.desiredHdrSdrRatio = desiredRatio;
    setTransactionFlags(eTransactionNeeded);
    return true;
}

bool Layer::setDesiredHdrHeadroom(float desiredRatio) {
    if (mDrawingState.desiredHdrSdrRatio == desiredRatio) return false;
    mDrawingState.desiredHdrSdrRatio = desiredRatio;
    setTransactionFlags(eTransactionNeeded);
    return true;
}

bool Layer::setSidebandStream(const sp<NativeHandle>& sidebandStream, const FrameTimelineInfo& info,
                              nsecs_t postTime, gui::GameMode gameMode) {
    if (mDrawingState.sidebandStream == sidebandStream) return false;

    if (mDrawingState.sidebandStream != nullptr && sidebandStream == nullptr) {
        mFlinger->mTunnelModeEnabledReporter->decrementTunnelModeCount();
    } else if (sidebandStream != nullptr) {
        mFlinger->mTunnelModeEnabledReporter->incrementTunnelModeCount();
    }

    mDrawingState.sidebandStream = sidebandStream;
    if (sidebandStream != nullptr && mDrawingState.buffer != nullptr) {
        releasePreviousBuffer();
        resetDrawingStateBufferInfo();
        mDrawingState.bufferSurfaceFrameTX = nullptr;
        setFrameTimelineVsyncForBufferlessTransaction(info, postTime, gameMode);
    }
    setTransactionFlags(eTransactionNeeded);
    if (!mSidebandStreamChanged.exchange(true)) {
        // mSidebandStreamChanged was false
        mFlinger->onLayerUpdate();
    }
    return true;
}

bool Layer::setTransactionCompletedListeners(const std::vector<sp<CallbackHandle>>& handles,
                                             bool willPresent) {
    // If there is no handle, we will not send a callback so reset mReleasePreviousBuffer and return
    if (handles.empty()) {
        mReleasePreviousBuffer = false;
        return false;
    }

    std::deque<sp<CallbackHandle>> remainingHandles;
    for (const auto& handle : handles) {
        // If this transaction set a buffer on this layer, release its previous buffer
        handle->releasePreviousBuffer = mReleasePreviousBuffer;

        // If this layer will be presented in this frame
        if (willPresent) {
            // If this transaction set an acquire fence on this layer, set its acquire time
            handle->acquireTimeOrFence = mCallbackHandleAcquireTimeOrFence;
            handle->frameNumber = mDrawingState.frameNumber;
            handle->previousFrameNumber = mDrawingState.previousFrameNumber;
            if (mPreviousReleaseBufferEndpoint == handle->listener) {
                // Add fence from previous screenshot now so that it can be dispatched to the
                // client.
                for (auto& [_, future] : mAdditionalPreviousReleaseFences) {
                    handle->previousReleaseFences.emplace_back(std::move(future));
                }
                mAdditionalPreviousReleaseFences.clear();
            }
            // Store so latched time and release fence can be set
            mDrawingState.callbackHandles.push_back(handle);

        } else { // If this layer will NOT need to be relatched and presented this frame
            // Queue this handle to be notified below.
            remainingHandles.push_back(handle);
        }
    }

    if (!remainingHandles.empty()) {
        // Notify the transaction completed threads these handles are done. These are only the
        // handles that were not added to the mDrawingState, which will be notified later.
        mFlinger->getTransactionCallbackInvoker().addCallbackHandles(remainingHandles);
    }

    mReleasePreviousBuffer = false;
    mCallbackHandleAcquireTimeOrFence = -1;

    return willPresent;
}

Rect Layer::getBufferSize(const State& /*s*/) const {
    // for buffer state layers we use the display frame size as the buffer size.

    if (mBufferInfo.mBuffer == nullptr) {
        return Rect::INVALID_RECT;
    }

    uint32_t bufWidth = mBufferInfo.mBuffer->getWidth();
    uint32_t bufHeight = mBufferInfo.mBuffer->getHeight();

    // Undo any transformations on the buffer and return the result.
    if (mBufferInfo.mTransform & ui::Transform::ROT_90) {
        std::swap(bufWidth, bufHeight);
    }

    if (getTransformToDisplayInverse()) {
        uint32_t invTransform = SurfaceFlinger::getActiveDisplayRotationFlags();
        if (invTransform & ui::Transform::ROT_90) {
            std::swap(bufWidth, bufHeight);
        }
    }

    return Rect(0, 0, static_cast<int32_t>(bufWidth), static_cast<int32_t>(bufHeight));
}

bool Layer::fenceHasSignaled() const {
    if (SurfaceFlinger::enableLatchUnsignaledConfig != LatchUnsignaledConfig::Disabled) {
        return true;
    }

    const bool fenceSignaled =
            getDrawingState().acquireFence->getStatus() == Fence::Status::Signaled;
    if (!fenceSignaled) {
        mFlinger->mTimeStats->incrementLatchSkipped(getSequence(),
                                                    TimeStats::LatchSkipReason::LateAcquire);
    }

    return fenceSignaled;
}

void Layer::onPreComposition(nsecs_t refreshStartTime) {
    for (const auto& handle : mDrawingState.callbackHandles) {
        handle->refreshStartTime = refreshStartTime;
    }
}

bool Layer::latchSidebandStream(bool& recomputeVisibleRegions) {
    if (mSidebandStreamChanged.exchange(false)) {
        const State& s(getDrawingState());
        // mSidebandStreamChanged was true
        mSidebandStream = s.sidebandStream;
        if (mSidebandStream != nullptr) {
            setTransactionFlags(eTransactionNeeded);
            mFlinger->setTransactionFlags(eTraversalNeeded);
        }
        recomputeVisibleRegions = true;
        return true;
    }
    return false;
}

void Layer::updateTexImage(nsecs_t latchTime, bool bgColorOnly) {
    const State& s(getDrawingState());

    if (!s.buffer) {
        if (bgColorOnly || mBufferInfo.mBuffer) {
            for (auto& handle : mDrawingState.callbackHandles) {
                handle->latchTime = latchTime;
            }
        }
        return;
    }

    for (auto& handle : mDrawingState.callbackHandles) {
        if (handle->frameNumber == mDrawingState.frameNumber) {
            handle->latchTime = latchTime;
        }
    }

    const int32_t layerId = getSequence();
    const uint64_t bufferId = mDrawingState.buffer->getId();
    const uint64_t frameNumber = mDrawingState.frameNumber;
    const auto acquireFence = std::make_shared<FenceTime>(mDrawingState.acquireFence);
    mFlinger->mTimeStats->setAcquireFence(layerId, frameNumber, acquireFence);
    mFlinger->mTimeStats->setLatchTime(layerId, frameNumber, latchTime);

    mFlinger->mFrameTracer->traceFence(layerId, bufferId, frameNumber, acquireFence,
                                       FrameTracer::FrameEvent::ACQUIRE_FENCE);
    mFlinger->mFrameTracer->traceTimestamp(layerId, bufferId, frameNumber, latchTime,
                                           FrameTracer::FrameEvent::LATCH);

    auto& bufferSurfaceFrame = mDrawingState.bufferSurfaceFrameTX;
    if (bufferSurfaceFrame != nullptr &&
        bufferSurfaceFrame->getPresentState() != PresentState::Presented) {
        // Update only if the bufferSurfaceFrame wasn't already presented. A Presented
        // bufferSurfaceFrame could be seen here if a pending state was applied successfully and we
        // are processing the next state.
        addSurfaceFramePresentedForBuffer(bufferSurfaceFrame,
                                          mDrawingState.acquireFenceTime->getSignalTime(),
                                          latchTime);
        mDrawingState.bufferSurfaceFrameTX.reset();
    }

    std::deque<sp<CallbackHandle>> remainingHandles;
    mFlinger->getTransactionCallbackInvoker()
            .addOnCommitCallbackHandles(mDrawingState.callbackHandles, remainingHandles);
    mDrawingState.callbackHandles = remainingHandles;
}

void Layer::gatherBufferInfo() {
    mPreviousReleaseCallbackId = {getCurrentBufferId(), mBufferInfo.mFrameNumber};
    mPreviousReleaseBufferEndpoint = mBufferInfo.mReleaseBufferEndpoint;
    if (!mDrawingState.buffer) {
        mBufferInfo = {};
        return;
    }

    if ((!mBufferInfo.mBuffer || !mDrawingState.buffer->hasSameBuffer(*mBufferInfo.mBuffer))) {
        decrementPendingBufferCount();
    }

    mBufferInfo.mBuffer = mDrawingState.buffer;
    mBufferInfo.mReleaseBufferEndpoint = mDrawingState.releaseBufferEndpoint;
    mBufferInfo.mFence = mDrawingState.acquireFence;
    mBufferInfo.mFrameNumber = mDrawingState.frameNumber;
    mBufferInfo.mPixelFormat =
            !mBufferInfo.mBuffer ? PIXEL_FORMAT_NONE : mBufferInfo.mBuffer->getPixelFormat();
    mBufferInfo.mFrameLatencyNeeded = true;
    mBufferInfo.mDesiredPresentTime = mDrawingState.desiredPresentTime;
    mBufferInfo.mFenceTime = std::make_shared<FenceTime>(mDrawingState.acquireFence);
    mBufferInfo.mTransform = mDrawingState.bufferTransform;
    auto lastDataspace = mBufferInfo.mDataspace;
    mBufferInfo.mDataspace = translateDataspace(mDrawingState.dataspace);
    if (mBufferInfo.mBuffer != nullptr) {
        auto& mapper = GraphicBufferMapper::get();
        // TODO: We should measure if it's faster to do a blind write if we're on newer api levels
        // and don't need to possibly remaps buffers.
        ui::Dataspace dataspace = ui::Dataspace::UNKNOWN;
        status_t err = OK;
        {
            SFTRACE_NAME("getDataspace");
            err = mapper.getDataspace(mBufferInfo.mBuffer->getBuffer()->handle, &dataspace);
        }
        if (err != OK || dataspace != mBufferInfo.mDataspace) {
            {
                SFTRACE_NAME("setDataspace");
                err = mapper.setDataspace(mBufferInfo.mBuffer->getBuffer()->handle,
                                          static_cast<ui::Dataspace>(mBufferInfo.mDataspace));
            }

            // Some GPU drivers may cache gralloc metadata which means before we composite we need
            // to upsert RenderEngine's caches. Put in a special workaround to be backwards
            // compatible with old vendors, with a ticking clock.
            static const int32_t kVendorVersion =
                    base::GetIntProperty("ro.board.api_level", __ANDROID_API_FUTURE__);
            if (const auto format =
                        static_cast<aidl::android::hardware::graphics::common::PixelFormat>(
                                mBufferInfo.mBuffer->getPixelFormat());
                err == OK && kVendorVersion < __ANDROID_API_U__ &&
                (format ==
                         aidl::android::hardware::graphics::common::PixelFormat::
                                 IMPLEMENTATION_DEFINED ||
                 format == aidl::android::hardware::graphics::common::PixelFormat::YCBCR_420_888 ||
                 format == aidl::android::hardware::graphics::common::PixelFormat::YV12 ||
                 format == aidl::android::hardware::graphics::common::PixelFormat::YCBCR_P010)) {
                mBufferInfo.mBuffer->remapBuffer();
            }
        }
    }
    if (lastDataspace != mBufferInfo.mDataspace ||
        mBufferInfo.mTimeSinceDataspaceUpdate == std::chrono::steady_clock::time_point::min()) {
        mFlinger->mHdrLayerInfoChanged = true;
        const auto currentTime = std::chrono::steady_clock::now();
        if (mBufferInfo.mTimeSinceDataspaceUpdate > std::chrono::steady_clock::time_point::min()) {
            mFlinger->mLayerEvents
                    .emplace_back(mOwnerUid, getSequence(), lastDataspace,
                                  std::chrono::duration_cast<std::chrono::milliseconds>(
                                          currentTime - mBufferInfo.mTimeSinceDataspaceUpdate));
        }
        mBufferInfo.mTimeSinceDataspaceUpdate = currentTime;
    }
    if (mBufferInfo.mDesiredHdrSdrRatio != mDrawingState.desiredHdrSdrRatio) {
        mBufferInfo.mDesiredHdrSdrRatio = mDrawingState.desiredHdrSdrRatio;
        mFlinger->mHdrLayerInfoChanged = true;
    }
    mBufferInfo.mCrop = computeBufferCrop(mDrawingState);
    mBufferInfo.mTransformToDisplayInverse = mDrawingState.transformToDisplayInverse;
}

Rect Layer::computeBufferCrop(const State& s) {
    if (s.buffer && !s.bufferCrop.isEmpty()) {
        Rect bufferCrop;
        s.buffer->getBounds().intersect(s.bufferCrop, &bufferCrop);
        return bufferCrop;
    } else if (s.buffer) {
        return s.buffer->getBounds();
    } else {
        return s.bufferCrop;
    }
}

void Layer::decrementPendingBufferCount() {
    int32_t pendingBuffers = --mPendingBuffers;
    tracePendingBufferCount(pendingBuffers);
}

void Layer::tracePendingBufferCount(int32_t pendingBuffers) {
    SFTRACE_INT(mBlastTransactionName.c_str(), pendingBuffers);
}

sp<LayerFE> Layer::getCompositionEngineLayerFE(
        const frontend::LayerHierarchy::TraversalPath& path) {
    for (auto& [p, layerFE] : mLayerFEs) {
        if (p == path) {
            return layerFE;
        }
    }
    auto layerFE = mFlinger->getFactory().createLayerFE(mName, this);
    mLayerFEs.emplace_back(path, layerFE);
    return layerFE;
}

void Layer::onCompositionPresented(const DisplayDevice* display,
                                   const std::shared_ptr<FenceTime>& glDoneFence,
                                   const std::shared_ptr<FenceTime>& presentFence,
                                   const CompositorTiming& compositorTiming,
                                   gui::GameMode gameMode) {
    // mFrameLatencyNeeded is true when a new frame was latched for the
    // composition.
    if (!mBufferInfo.mFrameLatencyNeeded) return;

    for (const auto& handle : mDrawingState.callbackHandles) {
        handle->gpuCompositionDoneFence = glDoneFence;
        handle->compositorTiming = compositorTiming;
    }

    // Update mDeprecatedFrameTracker.
    nsecs_t desiredPresentTime = mBufferInfo.mDesiredPresentTime;
    mDeprecatedFrameTracker.setDesiredPresentTime(desiredPresentTime);

    const int32_t layerId = getSequence();
    mFlinger->mTimeStats->setDesiredTime(layerId, mCurrentFrameNumber, desiredPresentTime);

    const auto outputLayer = findOutputLayerForDisplay(display);
    if (outputLayer && outputLayer->requiresClientComposition()) {
        nsecs_t clientCompositionTimestamp = outputLayer->getState().clientCompositionTimestamp;
        mFlinger->mFrameTracer->traceTimestamp(layerId, getCurrentBufferId(), mCurrentFrameNumber,
                                               clientCompositionTimestamp,
                                               FrameTracer::FrameEvent::FALLBACK_COMPOSITION);
        // Update the SurfaceFrames in the drawing state
        if (mDrawingState.bufferSurfaceFrameTX) {
            mDrawingState.bufferSurfaceFrameTX->setGpuComposition();
        }
        for (auto& [token, surfaceFrame] : mDrawingState.bufferlessSurfaceFramesTX) {
            surfaceFrame->setGpuComposition();
        }
    }

    // The SurfaceFrame's AcquireFence is the same as this.
    std::shared_ptr<FenceTime> frameReadyFence = mBufferInfo.mFenceTime;
    if (frameReadyFence->isValid()) {
        mDeprecatedFrameTracker.setFrameReadyFence(std::move(frameReadyFence));
    } else {
        // There was no fence for this frame, so assume that it was ready
        // to be presented at the desired present time.
        mDeprecatedFrameTracker.setFrameReadyTime(desiredPresentTime);
    }
    if (display) {
        const auto activeMode = display->refreshRateSelector().getActiveMode();
        const Fps refreshRate = activeMode.fps;
        const std::optional<Fps> renderRate =
                mFlinger->mScheduler->getFrameRateOverride(getOwnerUid());

        const auto vote = frameRateToSetFrameRateVotePayload(getFrameRateForLayerTree());

        if (presentFence->isValid()) {
            mFlinger->mTimeStats->setPresentFence(layerId, mCurrentFrameNumber, presentFence,
                                                  refreshRate, renderRate, vote, gameMode);
            mFlinger->mFrameTracer->traceFence(layerId, getCurrentBufferId(), mCurrentFrameNumber,
                                               presentFence,
                                               FrameTracer::FrameEvent::PRESENT_FENCE);
            mDeprecatedFrameTracker.setActualPresentFence(std::shared_ptr<FenceTime>(presentFence));
        } else if (const auto displayId = PhysicalDisplayId::tryCast(display->getId());
                   displayId && mFlinger->getHwComposer().isConnected(*displayId)) {
            // The HWC doesn't support present fences, so use the present timestamp instead.
            const nsecs_t presentTimestamp =
                    mFlinger->getHwComposer().getPresentTimestamp(*displayId);

            const nsecs_t now = systemTime(CLOCK_MONOTONIC);
            const nsecs_t vsyncPeriod =
                    mFlinger->getHwComposer()
                            .getDisplayVsyncPeriod(*displayId)
                            .value_opt()
                            .value_or(activeMode.modePtr->getVsyncRate().getPeriodNsecs());

            const nsecs_t actualPresentTime = now - ((now - presentTimestamp) % vsyncPeriod);

            mFlinger->mTimeStats->setPresentTime(layerId, mCurrentFrameNumber, actualPresentTime,
                                                 refreshRate, renderRate, vote, gameMode);
            mFlinger->mFrameTracer->traceTimestamp(layerId, getCurrentBufferId(),
                                                   mCurrentFrameNumber, actualPresentTime,
                                                   FrameTracer::FrameEvent::PRESENT_FENCE);
            mDeprecatedFrameTracker.setActualPresentTime(actualPresentTime);
        }
    }

    mFrameStatsHistorySize++;
    mDeprecatedFrameTracker.advanceFrame();
    mBufferInfo.mFrameLatencyNeeded = false;
}

bool Layer::latchBufferImpl(bool& recomputeVisibleRegions, nsecs_t latchTime, bool bgColorOnly) {
    SFTRACE_FORMAT_INSTANT("latchBuffer %s - %" PRIu64, getDebugName(),
                           getDrawingState().frameNumber);

    bool refreshRequired = latchSidebandStream(recomputeVisibleRegions);

    if (refreshRequired) {
        return refreshRequired;
    }

    // If the head buffer's acquire fence hasn't signaled yet, return and
    // try again later
    if (!fenceHasSignaled()) {
        SFTRACE_NAME("!fenceHasSignaled()");
        mFlinger->onLayerUpdate();
        return false;
    }
    updateTexImage(latchTime, bgColorOnly);

    // Capture the old state of the layer for comparisons later
    BufferInfo oldBufferInfo = mBufferInfo;
    mPreviousFrameNumber = mCurrentFrameNumber;
    mCurrentFrameNumber = mDrawingState.frameNumber;
    gatherBufferInfo();

    if (mBufferInfo.mBuffer) {
        // We latched a buffer that will be presented soon. Clear the previously presented layer
        // stack list.
        mPreviouslyPresentedLayerStacks.clear();
    }

    if (mDrawingState.buffer == nullptr) {
        const bool bufferReleased = oldBufferInfo.mBuffer != nullptr;
        recomputeVisibleRegions = bufferReleased;
        return bufferReleased;
    }

    if (oldBufferInfo.mBuffer == nullptr) {
        // the first time we receive a buffer, we need to trigger a
        // geometry invalidation.
        recomputeVisibleRegions = true;
    }

    if ((mBufferInfo.mCrop != oldBufferInfo.mCrop) ||
        (mBufferInfo.mTransform != oldBufferInfo.mTransform) ||
        (mBufferInfo.mTransformToDisplayInverse != oldBufferInfo.mTransformToDisplayInverse)) {
        recomputeVisibleRegions = true;
    }

    if (oldBufferInfo.mBuffer != nullptr) {
        uint32_t bufWidth = mBufferInfo.mBuffer->getWidth();
        uint32_t bufHeight = mBufferInfo.mBuffer->getHeight();
        if (bufWidth != oldBufferInfo.mBuffer->getWidth() ||
            bufHeight != oldBufferInfo.mBuffer->getHeight()) {
            recomputeVisibleRegions = true;
        }
    }
    return true;
}

bool Layer::getTransformToDisplayInverse() const {
    return mBufferInfo.mTransformToDisplayInverse;
}

ui::Dataspace Layer::translateDataspace(ui::Dataspace dataspace) {
    ui::Dataspace updatedDataspace = dataspace;
    // translate legacy dataspaces to modern dataspaces
    switch (dataspace) {
        // Treat unknown dataspaces as V0_sRGB
        case ui::Dataspace::UNKNOWN:
        case ui::Dataspace::SRGB:
            updatedDataspace = ui::Dataspace::V0_SRGB;
            break;
        case ui::Dataspace::SRGB_LINEAR:
            updatedDataspace = ui::Dataspace::V0_SRGB_LINEAR;
            break;
        case ui::Dataspace::JFIF:
            updatedDataspace = ui::Dataspace::V0_JFIF;
            break;
        case ui::Dataspace::BT601_625:
            updatedDataspace = ui::Dataspace::V0_BT601_625;
            break;
        case ui::Dataspace::BT601_525:
            updatedDataspace = ui::Dataspace::V0_BT601_525;
            break;
        case ui::Dataspace::BT709:
            updatedDataspace = ui::Dataspace::V0_BT709;
            break;
        default:
            break;
    }

    return updatedDataspace;
}

sp<GraphicBuffer> Layer::getBuffer() const {
    return mBufferInfo.mBuffer ? mBufferInfo.mBuffer->getBuffer() : nullptr;
}

bool Layer::setTrustedPresentationInfo(TrustedPresentationThresholds const& thresholds,
                                       TrustedPresentationListener const& listener) {
    bool hadTrustedPresentationListener = hasTrustedPresentationListener();
    mTrustedPresentationListener = listener;
    mTrustedPresentationThresholds = thresholds;
    bool haveTrustedPresentationListener = hasTrustedPresentationListener();
    if (!hadTrustedPresentationListener && haveTrustedPresentationListener) {
        mFlinger->mNumTrustedPresentationListeners++;
    } else if (hadTrustedPresentationListener && !haveTrustedPresentationListener) {
        mFlinger->mNumTrustedPresentationListeners--;
    }

    // Reset trusted presentation states to ensure we start the time again.
    mEnteredTrustedPresentationStateTime = -1;
    mLastReportedTrustedPresentationState = false;
    mLastComputedTrustedPresentationState = false;

    // If there's a new trusted presentation listener, the code needs to go through the composite
    // path to ensure it recomutes the current state and invokes the TrustedPresentationListener if
    // we're already in the requested state.
    return haveTrustedPresentationListener;
}

void Layer::setBufferReleaseChannel(
        const std::shared_ptr<gui::BufferReleaseChannel::ProducerEndpoint>& channel) {
    mBufferReleaseChannel = channel;
}

void Layer::updateLastLatchTime(nsecs_t latchTime) {
    mLastLatchTime = latchTime;
}

void Layer::setIsSmallDirty(frontend::LayerSnapshot* snapshot) {
    if (!mFlinger->mScheduler->supportSmallDirtyDetection(mOwnerAppId)) {
        snapshot->isSmallDirty = false;
        return;
    }

    if (mWindowType != WindowInfo::Type::APPLICATION &&
        mWindowType != WindowInfo::Type::BASE_APPLICATION) {
        snapshot->isSmallDirty = false;
        return;
    }

    Rect bounds = snapshot->surfaceDamage.getBounds();
    if (!bounds.isValid()) {
        snapshot->isSmallDirty = false;
        return;
    }

    // Transform to screen space.
    bounds = snapshot->localTransform.transform(bounds);

    // If the damage region is a small dirty, this could give the hint for the layer history that
    // it could suppress the heuristic rate when calculating.
    snapshot->isSmallDirty =
            mFlinger->mScheduler->isSmallDirtyArea(mOwnerAppId,
                                                   bounds.getWidth() * bounds.getHeight());
}

} // namespace android

#if defined(__gl_h_)
#error "don't include gl/gl.h in this file"
#endif

#if defined(__gl2_h_)
#error "don't include gl2/gl2.h in this file"
#endif

// TODO(b/129481165): remove the #pragma below and fix conversion issues
#pragma clang diagnostic pop // ignored "-Wconversion"
