94433bfc创建于 2024年8月13日历史提交
/*
 * Copyright (c) 2022 Huawei Device Co., Ltd.
 * 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.
 */

#include "minimize_app.h"

#include <ability_manager_client.h>
#include "window_manager_hilog.h"
#include "window_inner_manager.h"

namespace OHOS {
namespace Rosen {
namespace {
constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "MinimizeApp"};
}

std::map<MinimizeReason, std::vector<wptr<WindowNode>>> MinimizeApp::needMinimizeAppNodes_;
bool MinimizeApp::isMinimizedByOtherWindow_ = true;
std::recursive_mutex MinimizeApp::mutex_;
void MinimizeApp::AddNeedMinimizeApp(const sptr<WindowNode>& node, MinimizeReason reason)
{
    std::lock_guard<std::recursive_mutex> lock(mutex_);
    if (!EnableMinimize(reason)) {
        return;
    }
    if (!node) {
        WLOGFE("AddNeedMinimizeApp failed since node is nullptr");
        return;
    }
    wptr<WindowNode> weakNode(node);
    for (auto& appNodes: needMinimizeAppNodes_) {
        auto windowId = node->GetWindowId();
        auto iter = std::find_if(appNodes.second.begin(), appNodes.second.end(),
            [windowId](wptr<WindowNode> srcNode) {
                auto weakSrcNode = srcNode.promote();
                if (weakSrcNode == nullptr) {
                    return false;
                }
                return weakSrcNode->GetWindowId() == windowId;
            });
        if (iter != appNodes.second.end()) {
            WLOGI("[Minimize] Window %{public}u is already in minimize list", node->GetWindowId());
            return;
        }
    }
    WLOGI("[Minimize] Add Window %{public}u to minimize list, reason %{public}u", node->GetWindowId(), reason);
    needMinimizeAppNodes_[reason].emplace_back(weakNode);
}

std::vector<wptr<WindowNode>> MinimizeApp::GetNeedMinimizeAppNodesWithReason(MinimizeReason reason)
{
    std::lock_guard<std::recursive_mutex> lock(mutex_);
    std::vector<wptr<WindowNode>> needMinimizeAppNodes;
    if (needMinimizeAppNodes_.find(reason) != needMinimizeAppNodes_.end()) {
        for (auto& node : needMinimizeAppNodes_[reason]) {
            needMinimizeAppNodes.emplace_back(node);
        }
    }
    return needMinimizeAppNodes;
}

void MinimizeApp::ExecuteMinimizeAll()
{
    std::lock_guard<std::recursive_mutex> lock(mutex_);
    for (auto& appNodes: needMinimizeAppNodes_) {
        bool isFromUser = IsFromUser(appNodes.first);
        WLOGI("[Minimize] ExecuteMinimizeAll with size: %{public}zu, reason: %{public}u",
            appNodes.second.size(), appNodes.first);
        for (auto& node : appNodes.second) {
            WindowInnerManager::GetInstance().MinimizeAbility(node, isFromUser);
        }
        appNodes.second.clear();
    }
    needMinimizeAppNodes_.clear();
}

void MinimizeApp::ClearNodesWithReason(MinimizeReason reason)
{
    WLOGI("[Minimize] ClearNodesWithReason reason %{public}u", reason);
    std::lock_guard<std::recursive_mutex> lock(mutex_);
    if (needMinimizeAppNodes_.find(reason) != needMinimizeAppNodes_.end()) {
        needMinimizeAppNodes_.at(reason).clear();
    }
}

sptr<WindowNode> MinimizeApp::GetRecoverdNodeFromMinimizeList()
{
    WLOGI("[Minimize] RevertMinimizedNodeForTile");
    std::lock_guard<std::recursive_mutex> lock(mutex_);
    if (needMinimizeAppNodes_.find(MinimizeReason::LAYOUT_TILE) != needMinimizeAppNodes_.end()) {
        auto& tileNodesForMinimize = needMinimizeAppNodes_.at(MinimizeReason::LAYOUT_TILE);
        if (!tileNodesForMinimize.empty()) {
            auto recoverNode = tileNodesForMinimize.back().promote();
            tileNodesForMinimize.pop_back();
            return recoverNode;
        }
    }
    return nullptr;
}

bool MinimizeApp::IsNodeNeedMinimize(const sptr<WindowNode>& node)
{
    if (node == nullptr) {
        WLOGFE("[Minimize] node is nullptr");
        return false;
    }
    for (auto iter : needMinimizeAppNodes_) {
        auto nodes = iter.second;
        if (std::find(nodes.begin(), nodes.end(), node) != nodes.end()) {
            return true;
        }
    }
    return false;
}

bool MinimizeApp::IsNodeNeedMinimizeWithReason(const sptr<WindowNode>& node, MinimizeReason reason)
{
    if (node == nullptr) {
        WLOGFE("[Minimize] node is nullptr");
        return false;
    }
    if (needMinimizeAppNodes_.find(reason) == needMinimizeAppNodes_.end()) {
        WLOGFD("[Minimize] no need to minimize with id:%{public}u reason:%{public}u",
            node->GetWindowId(), reason);
        return false;
    }
    auto nodes = needMinimizeAppNodes_.at(reason);
    if (std::find(nodes.begin(), nodes.end(), node) != nodes.end()) {
        WLOGI("[Minimize] id:%{public}u need to minimize with reason:%{public}u",
            node->GetWindowId(), reason);
        return true;
    }
    return false;
}

bool MinimizeApp::EnableMinimize(MinimizeReason reason)
{
    bool isFromUser = IsFromUser(reason);
    if (!isMinimizedByOtherWindow_ && !isFromUser) {
        return false;
    }
    return true;
}

void MinimizeApp::ExecuteMinimizeTargetReasons(uint32_t reasons)
{
    std::lock_guard<std::recursive_mutex> lock(mutex_);
    while (reasons) {
        MinimizeReason reason = static_cast<MinimizeReason>(reasons & (~reasons + 1));
        if (needMinimizeAppNodes_.find(reason) != needMinimizeAppNodes_.end()) {
            WLOGI("[Minimize] ExecuteMinimizeTargetReason with size: %{public}zu, reason: %{public}u",
                needMinimizeAppNodes_.at(reason).size(), reason);
            bool isFromUser = IsFromUser(reason);
            for (auto& node : needMinimizeAppNodes_.at(reason)) {
                WindowInnerManager::GetInstance().MinimizeAbility(node, isFromUser);
            }
            needMinimizeAppNodes_.at(reason).clear();
        }
        reasons -= reason;
    }
}

void MinimizeApp::SetMinimizedByOtherConfig(bool isMinimizedByOther)
{
    isMinimizedByOtherWindow_ = isMinimizedByOther;
}
} // Rosen
} // OHOS