1 /*
2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #ifndef OHOS_ROSEN_CLIENT_AGENT_MANAGER_H
17 #define OHOS_ROSEN_CLIENT_AGENT_MANAGER_H
18
19 #include <map>
20 #include <mutex>
21 #include <set>
22 #include "agent_death_recipient.h"
23 #include "window_manager_hilog.h"
24
25 namespace OHOS {
26 namespace Rosen {
27 template <typename T1, typename T2>
28 class ClientAgentContainer {
29 public:
30 ClientAgentContainer();
31 virtual ~ClientAgentContainer() = default;
32
33 bool RegisterAgent(const sptr<T1>& agent, T2 type);
34 bool UnregisterAgent(const sptr<T1>& agent, T2 type);
35 std::set<sptr<T1>> GetAgentsByType(T2 type);
36
37 private:
38 void RemoveAgent(const sptr<IRemoteObject>& remoteObject);
39 bool UnregisterAgentLocked(std::set<sptr<T1>>& agents, const sptr<IRemoteObject>& agent);
40
41 static constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "ClientAgentContainer"};
42
43 struct finder_t {
finder_tfinder_t44 finder_t(sptr<IRemoteObject> remoteObject) : remoteObject_(remoteObject) {}
45
operatorfinder_t46 bool operator()(sptr<T1> agent)
47 {
48 return agent->AsObject() == remoteObject_;
49 }
50
51 sptr<IRemoteObject> remoteObject_;
52 };
53
54 std::recursive_mutex mutex_;
55 std::map<T2, std::set<sptr<T1>>> agentMap_;
56 sptr<AgentDeathRecipient> deathRecipient_;
57 };
58
59 template<typename T1, typename T2>
ClientAgentContainer()60 ClientAgentContainer<T1, T2>::ClientAgentContainer() : deathRecipient_(
61 new AgentDeathRecipient(std::bind(&ClientAgentContainer<T1, T2>::RemoveAgent, this, std::placeholders::_1))) {}
62
63 template<typename T1, typename T2>
RegisterAgent(const sptr<T1> & agent,T2 type)64 bool ClientAgentContainer<T1, T2>::RegisterAgent(const sptr<T1>& agent, T2 type)
65 {
66 std::lock_guard<std::recursive_mutex> lock(mutex_);
67 auto iter = std::find_if(agentMap_[type].begin(), agentMap_[type].end(), finder_t(agent->AsObject()));
68 if (iter != agentMap_[type].end()) {
69 WLOGFW("failed to register agent");
70 return false;
71 }
72 agentMap_[type].insert(agent);
73 if (deathRecipient_ == nullptr || !agent->AsObject()->AddDeathRecipient(deathRecipient_)) {
74 WLOGFI("failed to add death recipient");
75 }
76 return true;
77 }
78
79 template<typename T1, typename T2>
UnregisterAgent(const sptr<T1> & agent,T2 type)80 bool ClientAgentContainer<T1, T2>::UnregisterAgent(const sptr<T1>& agent, T2 type)
81 {
82 std::lock_guard<std::recursive_mutex> lock(mutex_);
83 if (agent == nullptr || agentMap_.count(type) == 0) {
84 WLOGFE("agent or type is invalid");
85 return false;
86 }
87 auto& agents = agentMap_.at(type);
88 bool ret = UnregisterAgentLocked(agents, agent->AsObject());
89 agent->AsObject()->RemoveDeathRecipient(deathRecipient_);
90 return ret;
91 }
92
93 template<typename T1, typename T2>
GetAgentsByType(T2 type)94 std::set<sptr<T1>> ClientAgentContainer<T1, T2>::GetAgentsByType(T2 type)
95 {
96 std::lock_guard<std::recursive_mutex> lock(mutex_);
97 if (agentMap_.count(type) == 0) {
98 WLOGFI("no such type of agent registered! type:%{public}u", type);
99 return std::set<sptr<T1>>();
100 }
101 return agentMap_.at(type);
102 }
103
104 template<typename T1, typename T2>
UnregisterAgentLocked(std::set<sptr<T1>> & agents,const sptr<IRemoteObject> & agent)105 bool ClientAgentContainer<T1, T2>::UnregisterAgentLocked(std::set<sptr<T1>>& agents,
106 const sptr<IRemoteObject>& agent)
107 {
108 auto iter = std::find_if(agents.begin(), agents.end(), finder_t(agent));
109 if (iter == agents.end()) {
110 WLOGFW("could not find this agent");
111 return false;
112 }
113 agents.erase(iter);
114 WLOGFI("agent unregistered");
115 return true;
116 }
117
118 template<typename T1, typename T2>
RemoveAgent(const sptr<IRemoteObject> & remoteObject)119 void ClientAgentContainer<T1, T2>::RemoveAgent(const sptr<IRemoteObject>& remoteObject)
120 {
121 WLOGFI("RemoveAgent");
122 std::lock_guard<std::recursive_mutex> lock(mutex_);
123 for (auto& elem : agentMap_) {
124 if (UnregisterAgentLocked(elem.second, remoteObject)) {
125 break;
126 }
127 }
128 remoteObject->RemoveDeathRecipient(deathRecipient_);
129 }
130 }
131 }
132 #endif // OHOS_ROSEN_CLIENT_AGENT_MANAGER_H
133