/* * 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" namespace OHOS { namespace Rosen { template class ClientAgentContainer { public: ClientAgentContainer(); virtual ~ClientAgentContainer() = default; bool RegisterAgent(const sptr& agent, T2 type); bool UnregisterAgent(const sptr& agent, T2 type); std::set> GetAgentsByType(T2 type); private: void RemoveAgent(const sptr& remoteObject); bool 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_; 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); bool ret = UnregisterAgentLocked(agents, agent->AsObject()); agent->AsObject()->RemoveDeathRecipient(deathRecipient_); return ret; } 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 bool 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 false; } agents.erase(iter); WLOGFI("agent unregistered"); return true; } template void ClientAgentContainer::RemoveAgent(const sptr& remoteObject) { WLOGFI("RemoveAgent"); std::lock_guard lock(mutex_); for (auto& elem : agentMap_) { if (UnregisterAgentLocked(elem.second, remoteObject)) { break; } } remoteObject->RemoveDeathRecipient(deathRecipient_); } } } #endif // OHOS_ROSEN_CLIENT_AGENT_MANAGER_H