/*
 * Copyright 2022 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.
 */

// #define LOG_NDEBUG 0
#define ATRACE_TAG ATRACE_TAG_GRAPHICS

#include "LayerLifecycleManager.h"

#include <android-base/logging.h>
#include <ui/LayerStack.h>

#include "Client.h" // temporarily needed for LayerCreationArgs
#include "LayerLog.h"
#include "SwapErase.h"

namespace android::surfaceflinger::frontend {

using namespace ftl::flag_operators;

namespace {
// Returns true if the layer is root of a display and can be mirrored by mirroringLayer
bool canMirrorRootLayer(const RequestedLayerState& mirrorLayer,
                        const RequestedLayerState& rootLayer) {
    return rootLayer.isRoot() && rootLayer.layerStack != ui::UNASSIGNED_LAYER_STACK &&
            rootLayer.layerStack == mirrorLayer.layerStackToMirror &&
            rootLayer.id != mirrorLayer.id;
}
} // namespace

// Register a `mirrorLayer`, and link it to the references of the root layer that the `mirrorLayer`
// mirrors.
void LayerLifecycleManager::doMirror(RequestedLayerState& mirrorLayer) {
    // If this layer is mirroring a layer stack, then walk though all the existing root
    // layers for the layer stack and add them as children to be mirrored.
    mGlobalChanges |= RequestedLayerState::Changes::Hierarchy;
    mirrorLayer.changes |= RequestedLayerState::Changes::Mirror;
    mLayersMirroringLayerStack.push_back(mirrorLayer.id);
    for (std::unique_ptr<RequestedLayerState>& mayBeRootLayer : mLayers) {
        if (canMirrorRootLayer(mirrorLayer, *mayBeRootLayer)) {
            mirrorLayer.mirrorIds.push_back(mayBeRootLayer->id);
            linkLayer(mayBeRootLayer->id, mirrorLayer.id);
        }
    }
}

void LayerLifecycleManager::undoMirror(RequestedLayerState& mirrorLayer) {
    mGlobalChanges |= RequestedLayerState::Changes::Hierarchy;
    mirrorLayer.changes |= RequestedLayerState::Changes::Mirror;
    swapErase(mLayersMirroringLayerStack, mirrorLayer.id);
    for (uint32_t layerId : mirrorLayer.mirrorIds) {
        if (std::vector<uint32_t /*layerId*/>* references = getLinkedLayersFromId(layerId);
            references != nullptr) {
            swapErase(*references, mirrorLayer.id);
        }
    }
    mirrorLayer.mirrorIds.clear();
}

void LayerLifecycleManager::addLayers(std::vector<std::unique_ptr<RequestedLayerState>> newLayers) {
    if (newLayers.empty()) {
        return;
    }

    mGlobalChanges |= RequestedLayerState::Changes::Hierarchy;
    for (std::unique_ptr<RequestedLayerState>& newLayer : newLayers) {
        RequestedLayerState& layer = *newLayer.get();
        auto [it, inserted] = mIdToLayer.try_emplace(layer.id, References{.owner = layer});
        LLOG_ALWAYS_FATAL_WITH_TRACE_IF(!inserted,
                                        "Duplicate layer id found. New layer: %s Existing layer: "
                                        "%s",
                                        layer.getDebugString().c_str(),
                                        it->second.owner.getDebugString().c_str());

        mAddedLayers.push_back(newLayer.get());
        mChangedLayers.push_back(newLayer.get());
        layer.parentId = linkLayer(layer.parentId, layer.id);
        layer.relativeParentId = linkLayer(layer.relativeParentId, layer.id);

        if (layer.layerStackToMirror != ui::UNASSIGNED_LAYER_STACK) {
            // Set mirror layer's default layer stack to -1 so it doesn't end up rendered on a
            // display accidentally.
            // TODO: b/460564504 - The client should be able to specify if the layer is root or not,
            // that way unassigning the layer stack is not necessary.
            layer.layerStack = ui::UNASSIGNED_LAYER_STACK;
            doMirror(layer);
        } else if (layer.displayIdToMirror.has_value()) {
            layer.layerStack = ui::UNASSIGNED_LAYER_STACK;
        } else {
            layer.layerIdToMirror = linkLayer(layer.layerIdToMirror, layer.id);
        }
        layer.touchCropId = linkLayer(layer.touchCropId, layer.id);
        if (layer.isRoot()) {
            updateDisplayMirrorLayers(layer);
        }
        LLOGV(layer.id, "%s", layer.getDebugString().c_str());
        mLayers.emplace_back(std::move(newLayer));
    }
}

void LayerLifecycleManager::updateDisplayMirrors(
        const ui::DisplayMap<ui::LayerStack, frontend::DisplayInfo>& frontEndDisplaysInfo,
        bool frontEndDisplaysInfoChanged) {
    if (!frontEndDisplaysInfoChanged && mAddedLayers.empty()) {
        return;
    }

    for (const std::unique_ptr<RequestedLayerState>& layer : mLayers) {
        LOG_IF(FATAL, layer == nullptr)
                << "Null layer found when iterating mLayers in " << __func__;
        if (!layer->displayIdToMirror.has_value()) {
            continue;
        }
        const auto displayInfoIter =
                std::find_if(frontEndDisplaysInfo.begin(), frontEndDisplaysInfo.end(),
                             [&](const std::pair<ui::LayerStack, frontend::DisplayInfo>& pair)
                                     -> bool {
                                 return *(layer->displayIdToMirror) == pair.second.displayId;
                             });
        if (displayInfoIter == frontEndDisplaysInfo.end()) {
            layer->layerStackToMirror = ui::UNASSIGNED_LAYER_STACK;
            undoMirror(*layer);
            continue;
        }
        const ui::LayerStack layerStack = displayInfoIter->first;
        if (layer->layerStackToMirror == layerStack) {
            continue;
        }
        // The logic below handles three cases:
        // - If the layer stack to mirror transitions from unassigned to assigned, then mirror the
        // hierarchy associated to the assigned layer stack.
        // - If the layer stack to mirror transitions from assigned to unassigned, then unmirror the
        // hierarhcy.
        // - If the layer stack to mirror transitions from assigned layer stack to a different
        // assigned layer stack, then update the mirror references by re-registering the mirror
        // layer.
        if (layer->layerStackToMirror != ui::UNASSIGNED_LAYER_STACK) {
            undoMirror(*layer);
        }
        layer->layerStackToMirror = layerStack;
        if (layer->layerStackToMirror != ui::UNASSIGNED_LAYER_STACK) {
            doMirror(*layer);
        }
    }
}

void LayerLifecycleManager::onHandlesDestroyed(
        const std::vector<std::pair<uint32_t, std::string /* debugName */>>& destroyedHandles,
        bool ignoreUnknownHandles) {
    std::vector<uint32_t> layersToBeDestroyed;
    for (const auto& [layerId, name] : destroyedHandles) {
        auto it = mIdToLayer.find(layerId);
        if (it == mIdToLayer.end()) {
            LLOG_ALWAYS_FATAL_WITH_TRACE_IF(!ignoreUnknownHandles, "%s Layerid not found %s[%d]",
                                            __func__, name.c_str(), layerId);
            continue;
        }
        RequestedLayerState& layer = it->second.owner;
        LLOGV(layer.id, "%s", layer.getDebugString().c_str());
        layer.handleAlive = false;
        if (!layer.canBeDestroyed()) {
            continue;
        }
        layer.changes |= RequestedLayerState::Changes::Destroyed;
        layersToBeDestroyed.emplace_back(layerId);
    }

    if (layersToBeDestroyed.empty()) {
        return;
    }

    mGlobalChanges |= RequestedLayerState::Changes::Hierarchy;
    for (size_t i = 0; i < layersToBeDestroyed.size(); i++) {
        uint32_t layerId = layersToBeDestroyed[i];
        auto it = mIdToLayer.find(layerId);
        LLOG_ALWAYS_FATAL_WITH_TRACE_IF(it == mIdToLayer.end(), "%s Layer with id %d not found",
                                        __func__, layerId);

        RequestedLayerState& layer = it->second.owner;

        layer.parentId = unlinkLayer(layer.parentId, layer.id);
        layer.relativeParentId = unlinkLayer(layer.relativeParentId, layer.id);
        if (layer.layerStackToMirror != ui::UNASSIGNED_LAYER_STACK) {
            layer.mirrorIds = unlinkLayers(layer.mirrorIds, layer.id);
            swapErase(mLayersMirroringLayerStack, layer.id);
        } else {
            layer.layerIdToMirror = unlinkLayer(layer.layerIdToMirror, layer.id);
            layer.mirrorIds.clear();
        }

        layer.touchCropId = unlinkLayer(layer.touchCropId, layer.id);

        auto& references = it->second.references;
        for (uint32_t linkedLayerId : references) {
            RequestedLayerState* linkedLayer = getLayerFromId(linkedLayerId);
            LLOG_ALWAYS_FATAL_WITH_TRACE_IF(!linkedLayer,
                                            "%s Layerid reference %d not found for %d", __func__,
                                            linkedLayerId, layer.id);
            if (linkedLayer->parentId == layer.id) {
                linkedLayer->parentId = UNASSIGNED_LAYER_ID;
                if (linkedLayer->canBeDestroyed()) {
                    linkedLayer->changes |= RequestedLayerState::Changes::Destroyed;
                    layersToBeDestroyed.emplace_back(linkedLayer->id);
                }
            }
            if (linkedLayer->relativeParentId == layer.id) {
                linkedLayer->relativeParentId = UNASSIGNED_LAYER_ID;
            }
            if (swapErase(linkedLayer->mirrorIds, layer.id)) {
                linkedLayer->changes |= RequestedLayerState::Changes::Mirror;
            }
            if (linkedLayer->layerIdToMirror == layer.id) {
                linkedLayer->layerIdToMirror = UNASSIGNED_LAYER_ID;
                linkedLayer->changes |= RequestedLayerState::Changes::Mirror;
            }
            if (linkedLayer->touchCropId == layer.id) {
                linkedLayer->touchCropId = UNASSIGNED_LAYER_ID;
            }
        }
        mIdToLayer.erase(it);
    }

    auto it = mLayers.begin();
    while (it != mLayers.end()) {
        RequestedLayerState* layer = it->get();
        if (layer->changes.test(RequestedLayerState::Changes::Destroyed)) {
            LLOGV(layer->id, "destroyed %s", layer->getDebugStringShort().c_str());
            std::iter_swap(it, mLayers.end() - 1);
            mDestroyedLayers.emplace_back(std::move(mLayers.back()));
            if (it == mLayers.end() - 1) {
                it = mLayers.erase(mLayers.end() - 1);
            } else {
                mLayers.erase(mLayers.end() - 1);
            }
        } else {
            it++;
        }
    }
}

void LayerLifecycleManager::applyTransactions(
        const std::vector<QueuedTransactionState>& transactions, bool ignoreUnknownLayers) {
    for (const auto& transaction : transactions) {
        for (const auto& resolvedComposerState : transaction.states) {
            const auto& clientState = resolvedComposerState.state;
            uint32_t layerId = resolvedComposerState.layerId;
            if (layerId == UNASSIGNED_LAYER_ID) {
                ALOGW("%s Handle %p is not valid", __func__, clientState.surface.get());
                continue;
            }

            RequestedLayerState* layer = getLayerFromId(layerId);
            if (layer == nullptr) {
                LLOG_ALWAYS_FATAL_WITH_TRACE_IF(!ignoreUnknownLayers,
                                                "%s Layer with layerid=%d not found", __func__,
                                                layerId);
                continue;
            }

            LLOG_ALWAYS_FATAL_WITH_TRACE_IF(!layer->handleAlive,
                                            "%s Layer's with layerid=%d) is not alive. Possible "
                                            "out of "
                                            "order LayerLifecycleManager updates",
                                            __func__, layerId);

            if (layer->changes.get() == 0) {
                mChangedLayers.push_back(layer);
            }

            if (transaction.flags & ISurfaceComposer::eAnimation) {
                layer->changes |= RequestedLayerState::Changes::Animation;
            }

            uint32_t oldParentId = layer->parentId;
            uint32_t oldRelativeParentId = layer->relativeParentId;
            uint32_t oldTouchCropId = layer->touchCropId;
            layer->merge(resolvedComposerState);
            layer->lastUpdateTime = transaction.postTime;

            if (layer->what & layer_state_t::eBackgroundColorChanged) {
                RequestedLayerState* bgColorLayer = nullptr;
                if (layer->bgColorLayerId != UNASSIGNED_LAYER_ID) {
                    bgColorLayer = getLayerFromId(layer->bgColorLayerId);
                    if (bgColorLayer == nullptr) {
                        LLOG_ALWAYS_FATAL_WITH_TRACE_IF(!ignoreUnknownLayers,
                                                        "%s Background color layer with layerid=%d "
                                                        "not found",
                                                        __func__, layer->bgColorLayerId);
                        layer->bgColorLayerId = UNASSIGNED_LAYER_ID;
                    }
                }
                if (bgColorLayer == nullptr && layer->bgColor.a != 0) {
                    // Case 1: The background layer doesn't exist and the background color has a
                    // non-zero alpha. Create a background layer.
                    LayerCreationArgs
                            backgroundLayerArgs(LayerCreationArgs::getInternalLayerId(
                                                        LayerCreationArgs::sInternalSequence++),
                                                /*internalLayer=*/true);
                    backgroundLayerArgs.parentId = layer->id;
                    backgroundLayerArgs.name = layer->name + "BackgroundColorLayer";
                    backgroundLayerArgs.flags = ISurfaceComposerClient::eFXSurfaceEffect;
                    std::vector<std::unique_ptr<RequestedLayerState>> newLayers;
                    newLayers.emplace_back(
                            std::make_unique<RequestedLayerState>(backgroundLayerArgs));
                    RequestedLayerState* backgroundLayer = newLayers.back().get();
                    backgroundLayer->bgColorLayer = true;
                    backgroundLayer->handleAlive = false;
                    backgroundLayer->parentId = layer->id;
                    backgroundLayer->z = std::numeric_limits<int32_t>::min();
                    backgroundLayer->color = layer->bgColor;
                    backgroundLayer->dataspace = layer->bgColorDataspace;
                    layer->bgColorLayerId = backgroundLayer->id;
                    addLayers({std::move(newLayers)});
                } else if (bgColorLayer != nullptr && layer->bgColor.a == 0) {
                    // Case 2: The background layer exists and the background color has a zero
                    // alpha (invisible). Destroy the background layer.
                    layer->bgColorLayerId = UNASSIGNED_LAYER_ID;
                    bgColorLayer->parentId = unlinkLayer(bgColorLayer->parentId, bgColorLayer->id);
                    onHandlesDestroyed({{bgColorLayer->id, bgColorLayer->debugName}});
                } else if (bgColorLayer != nullptr && layer->bgColor.a != 0) {
                    // Case 3: The background layer exists and the background color alpha might
                    // have changed. Update the background layer.
                    bgColorLayer->color = layer->bgColor;
                    bgColorLayer->dataspace = layer->bgColorDataspace;
                    bgColorLayer->what |= layer_state_t::eColorChanged |
                            layer_state_t::eDataspaceChanged | layer_state_t::eAlphaChanged;
                    bgColorLayer->changes |= RequestedLayerState::Changes::Content;
                    mChangedLayers.push_back(bgColorLayer);
                    mGlobalChanges |= RequestedLayerState::Changes::Content;
                }
            }

            if (oldParentId != layer->parentId) {
                unlinkLayer(oldParentId, layer->id);
                layer->parentId = linkLayer(layer->parentId, layer->id);
                if (oldParentId == UNASSIGNED_LAYER_ID) {
                    updateDisplayMirrorLayers(*layer);
                }
            }
            if (layer->what & layer_state_t::eLayerStackChanged && layer->isRoot()) {
                updateDisplayMirrorLayers(*layer);
            }
            if (oldRelativeParentId != layer->relativeParentId) {
                unlinkLayer(oldRelativeParentId, layer->id);
                layer->relativeParentId = linkLayer(layer->relativeParentId, layer->id);
            }
            if (oldTouchCropId != layer->touchCropId) {
                unlinkLayer(oldTouchCropId, layer->id);
                layer->touchCropId = linkLayer(layer->touchCropId, layer->id);
            }

            mGlobalChanges |= layer->changes;
        }
    }
}

void LayerLifecycleManager::commitChanges() {
    for (auto layer : mAddedLayers) {
        for (auto& listener : mListeners) {
            listener->onLayerAdded(*layer);
        }
    }
    mAddedLayers.clear();

    for (auto& layer : mLayers) {
        layer->clearChanges();
    }

    for (auto& destroyedLayer : mDestroyedLayers) {
        for (auto& listener : mListeners) {
            listener->onLayerDestroyed(*destroyedLayer);
        }
    }
    mDestroyedLayers.clear();
    mChangedLayers.clear();
    mGlobalChanges.clear();
}

void LayerLifecycleManager::addLifecycleListener(std::shared_ptr<ILifecycleListener> listener) {
    mListeners.emplace_back(std::move(listener));
}

void LayerLifecycleManager::removeLifecycleListener(std::shared_ptr<ILifecycleListener> listener) {
    swapErase(mListeners, listener);
}

const std::vector<std::unique_ptr<RequestedLayerState>>& LayerLifecycleManager::getLayers() const {
    return mLayers;
}

const std::vector<std::unique_ptr<RequestedLayerState>>& LayerLifecycleManager::getDestroyedLayers()
        const {
    return mDestroyedLayers;
}

const std::vector<RequestedLayerState*>& LayerLifecycleManager::getChangedLayers() const {
    return mChangedLayers;
}

const ftl::Flags<RequestedLayerState::Changes> LayerLifecycleManager::getGlobalChanges() const {
    return mGlobalChanges;
}

const RequestedLayerState* LayerLifecycleManager::getLayerFromId(uint32_t id) const {
    if (id == UNASSIGNED_LAYER_ID) {
        return nullptr;
    }
    auto it = mIdToLayer.find(id);
    if (it == mIdToLayer.end()) {
        return nullptr;
    }
    return &it->second.owner;
}

RequestedLayerState* LayerLifecycleManager::getLayerFromId(uint32_t id) {
    if (id == UNASSIGNED_LAYER_ID) {
        return nullptr;
    }
    auto it = mIdToLayer.find(id);
    if (it == mIdToLayer.end()) {
        return nullptr;
    }
    return &it->second.owner;
}

std::vector<uint32_t>* LayerLifecycleManager::getLinkedLayersFromId(uint32_t id) {
    if (id == UNASSIGNED_LAYER_ID) {
        return nullptr;
    }
    auto it = mIdToLayer.find(id);
    if (it == mIdToLayer.end()) {
        return nullptr;
    }
    return &it->second.references;
}

uint32_t LayerLifecycleManager::linkLayer(uint32_t layerId, uint32_t layerToLink) {
    if (layerId == UNASSIGNED_LAYER_ID) {
        return UNASSIGNED_LAYER_ID;
    }

    std::vector<uint32_t>* linkedLayers = getLinkedLayersFromId(layerId);
    if (!linkedLayers) {
        ALOGV("Could not find layer id %d to link %d. Parent is probably destroyed", layerId,
              layerToLink);
        return UNASSIGNED_LAYER_ID;
    }
    linkedLayers->emplace_back(layerToLink);
    return layerId;
}

uint32_t LayerLifecycleManager::unlinkLayer(uint32_t layerId, uint32_t linkedLayer) {
    std::vector<uint32_t>* linkedLayers = getLinkedLayersFromId(layerId);
    if (!linkedLayers) {
        return UNASSIGNED_LAYER_ID;
    }
    swapErase(*linkedLayers, linkedLayer);
    return UNASSIGNED_LAYER_ID;
}

std::vector<uint32_t> LayerLifecycleManager::unlinkLayers(const std::vector<uint32_t>& layerIds,
                                                          uint32_t linkedLayer) {
    for (uint32_t layerId : layerIds) {
        unlinkLayer(layerId, linkedLayer);
    }
    return {};
}

std::string LayerLifecycleManager::References::getDebugString() const {
    std::string debugInfo = owner.name + "[" + std::to_string(owner.id) + "] refs:";
    std::for_each(references.begin(), references.end(),
                  [&debugInfo = debugInfo](const uint32_t& reference) mutable {
                      debugInfo += std::to_string(reference) + ",";
                  });
    return debugInfo;
}

void LayerLifecycleManager::fixRelativeZLoop(uint32_t relativeRootId) {
    auto it = mIdToLayer.find(relativeRootId);
    if (it == mIdToLayer.end()) {
        return;
    }
    RequestedLayerState& layer = it->second.owner;
    layer.relativeParentId = unlinkLayer(layer.relativeParentId, layer.id);
    layer.changes |=
            RequestedLayerState::Changes::Hierarchy | RequestedLayerState::Changes::RelativeParent;
    mGlobalChanges |= RequestedLayerState::Changes::Hierarchy;
}

// Some layers mirror the entire display stack. Since we don't have a single root layer per display
// we have to track all these layers and update what they mirror when the list of root layers
// on a display changes. This function walks through the list of display mirroring layers
// and updates its list of layers that its mirroring. This function should be called when a new
// root layer is added, removed or moved to another display.
void LayerLifecycleManager::updateDisplayMirrorLayers(RequestedLayerState& rootLayer) {
    for (uint32_t mirroringLayerId : mLayersMirroringLayerStack) {
        RequestedLayerState* mirrorLayer = getLayerFromId(mirroringLayerId);
        bool canBeMirrored = canMirrorRootLayer(*mirrorLayer, rootLayer);
        bool currentlyMirrored =
                std::find(mirrorLayer->mirrorIds.begin(), mirrorLayer->mirrorIds.end(),
                          rootLayer.id) != mirrorLayer->mirrorIds.end();

        if (canBeMirrored && !currentlyMirrored) {
            mirrorLayer->mirrorIds.emplace_back(rootLayer.id);
            linkLayer(rootLayer.id, mirrorLayer->id);
            mirrorLayer->changes |= RequestedLayerState::Changes::Mirror;
        } else if (!canBeMirrored && currentlyMirrored) {
            swapErase(mirrorLayer->mirrorIds, rootLayer.id);
            unlinkLayer(rootLayer.id, mirrorLayer->id);
            mirrorLayer->changes |= RequestedLayerState::Changes::Mirror;
        }
    }
}

base::expected<bool, status_t> LayerLifecycleManager::isLayerSecure(
        uint32_t layerId, std::unordered_set<uint32_t>& visited) const {
    if (layerId == UNASSIGNED_LAYER_ID) {
        return false;
    }

    auto const [it, newVisit] = visited.insert(layerId);
    if (!newVisit) {
        ALOGV("Cycle detected at layer ID %d", layerId);
        return base::unexpected(BAD_VALUE);
    }

    if (getLayerFromId(layerId)->flags & layer_state_t::eLayerSecure) {
        return true;
    }
    return isLayerSecure(getLayerFromId(layerId)->parentId, visited);
}

} // namespace android::surfaceflinger::frontend
