/* * Copyright (c) 2021-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. */ #ifndef OHOS_ROSEN_CLIENT_AGENT_MANAGER_H #define OHOS_ROSEN_CLIENT_AGENT_MANAGER_H #include #include #include #include "agent_death_recipient.h" #include "window_manager_hilog.h" #include "zidl/display_manager_agent_interface.h" namespace OHOS { namespace Rosen { template class ClientAgentContainer { using DestroyCallback = std::function)>; public: ClientAgentContainer(); virtual ~ClientAgentContainer() = default; bool RegisterAgent(const sptr& agent, T2 type); bool UnregisterAgent(const sptr& agent, T2 type); bool SetRemoveAgentCallback(const DestroyCallback& callback, T2 type); std::set> GetAgentsByType(T2 type); private: void RemoveAgent(const sptr& remoteObject); sptr UnregisterAgentLocked(std::set>& agents, const sptr& agent); static constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "ClientAgentContainer"}; struct finder_t { finder_t(sptr remoteObject) : remoteObject_(remoteObject) {} bool operator()(sptr agent) { return agent->AsObject() == remoteObject_; } sptr remoteObject_; }; std::recursive_mutex mutex_; std::map>> agentMap_; std::map callbackMap_; sptr deathRecipient_; }; template ClientAgentContainer::ClientAgentContainer() : deathRecipient_( new AgentDeathRecipient(std::bind(&ClientAgentContainer::RemoveAgent, this, std::placeholders::_1))) {} template bool ClientAgentContainer::RegisterAgent(const sptr& agent, T2 type) { std::lock_guard lock(mutex_); auto iter = std::find_if(agentMap_[type].begin(), agentMap_[type].end(), finder_t(agent->AsObject())); if (iter != agentMap_[type].end()) { WLOGFW("failed to register agent"); return false; } agentMap_[type].insert(agent); if (deathRecipient_ == nullptr || !agent->AsObject()->AddDeathRecipient(deathRecipient_)) { WLOGFI("failed to add death recipient"); } return true; } template bool ClientAgentContainer::UnregisterAgent(const sptr& agent, T2 type) { std::lock_guard lock(mutex_); if (agent == nullptr || agentMap_.count(type) == 0) { WLOGFE("agent or type is invalid"); return false; } auto& agents = agentMap_.at(type); WLOGFI("UnregisterAgent: agent: %{public}p in ClientAgentContainer", agent->AsObject().GetRefPtr()); auto ret = UnregisterAgentLocked(agents, agent->AsObject()); if (ret != nullptr) { agent->AsObject()->RemoveDeathRecipient(deathRecipient_); } return true; } template bool ClientAgentContainer::SetRemoveAgentCallback(const DestroyCallback& callback, T2 type) { callbackMap_[type] = callback; WLOG_I("ClientAgentContainer callback registered type:%{public}u", type); return true; } template std::set> ClientAgentContainer::GetAgentsByType(T2 type) { std::lock_guard lock(mutex_); if (agentMap_.count(type) == 0) { WLOGFI("no such type of agent registered! type:%{public}u", type); return std::set>(); } return agentMap_.at(type); } template sptr ClientAgentContainer::UnregisterAgentLocked(std::set>& agents, const sptr& agent) { auto iter = std::find_if(agents.begin(), agents.end(), finder_t(agent)); if (iter == agents.end()) { WLOGFW("could not find this agent"); return nullptr; } auto res = *iter; agents.erase(iter); return res; } template void ClientAgentContainer::RemoveAgent(const sptr& remoteObject) { WLOGFI("RemoveAgent"); std::lock_guard lock(mutex_); DestroyCallback removeAgentCallback = nullptr; for (auto& elem : agentMap_) { auto agent = UnregisterAgentLocked(elem.second, remoteObject); if (agent != nullptr) { if (callbackMap_[elem.first] != nullptr) { removeAgentCallback = callbackMap_[elem.first]; removeAgentCallback(remoteObject); } break; } } remoteObject->RemoveDeathRecipient(deathRecipient_); } } } #endif // OHOS_ROSEN_CLIENT_AGENT_MANAGER_H