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 REMOTE_OBSERVER_LIST_H
17 #define REMOTE_OBSERVER_LIST_H
18 
19 #include <functional>
20 #include <map>
21 #include <mutex>
22 #include <tuple>
23 
24 #include "refbase.h"
25 #include "iremote_broker.h"
26 #include "iremote_proxy.h"
27 #include "bluetooth_log.h"
28 
29 namespace OHOS {
30 namespace Bluetooth {
31 template <typename T, typename... Args>
32 class RemoteObserverList final {
33     using DrCallbackFunc = std::function<void(const sptr<T> &observer, Args... args)>;
34 public:
35     RemoteObserverList() = default;
36     ~RemoteObserverList();
37     bool Register(const sptr<T> &observer, DrCallbackFunc func, Args... args);
38     bool Deregister(const sptr<T> &observer);
39     void ForEach(const std::function<void(sptr<T>)> &observer);
40 
41     class ObserverDeathRecipient : public IRemoteObject::DeathRecipient {
42     public:
43         ObserverDeathRecipient(const sptr<T> &observer, RemoteObserverList<T, Args...> *owner);
GetObserver()44         sptr<T> GetObserver() const
45         {
46             return observer_;
47         };
48         void OnRemoteDied(const wptr<IRemoteObject> &remote) override;
49 
50     private:
51         sptr<T> observer_ {};
52         RemoteObserverList<T, Args...> *owner_ {};
53     };
54     std::mutex lock_ {};
55     using ObserverMap = std::map<sptr<T>, sptr<ObserverDeathRecipient>>;
56     ObserverMap observers_ {};
57 
58     struct RtOberserInfo {
59         DrCallbackFunc callbackFunc;
60         std::tuple<Args...> args;
61     };
62     using BtServerMap = std::map<sptr<T>, RtOberserInfo> ;
63     BtServerMap btServers_ {};
64 
65     RemoteObserverList(const RemoteObserverList &) = delete;
66     RemoteObserverList &operator=(const RemoteObserverList &) = delete;
67 
68 private:
69     bool UnregisterInternal(typename ObserverMap::iterator iter);
70 };
71 
72 template <typename T, typename... Args>
~RemoteObserverList()73 RemoteObserverList<T, Args...>::~RemoteObserverList()
74 {
75     HILOGI("RemoteObserverList<T, Args...>::~RemoteObserverList() called");
76     std::lock_guard<std::mutex> lock(lock_);
77     for (auto it = observers_.begin(); it != observers_.end(); ++it) {
78         sptr<ObserverDeathRecipient> dr = it->second;
79         if (!dr->GetObserver()->AsObject()->RemoveDeathRecipient(dr)) {
80             HILOGE("Failed to unlink death recipient from observer");
81         }
82     }
83     observers_.clear();
84     btServers_.clear();
85 }
86 
87 template <typename T, typename... Args>
Register(const sptr<T> & observer,DrCallbackFunc func,Args...args)88 bool RemoteObserverList<T, Args...>::Register(const sptr<T> &observer, DrCallbackFunc func, Args... args)
89 {
90     HILOGI("RemoteObserverList<T, Args...>::Register called");
91     std::lock_guard<std::mutex> lock(lock_);
92     bool isMatch = false;
93     for (const auto &it : observers_) {
94         if (it.first != nullptr && it.first->AsObject() == observer->AsObject()) {
95             HILOGW("Observer list already contains given observer");
96             isMatch = true;
97             break;
98         }
99     }
100     if (!isMatch) {
101         sptr<ObserverDeathRecipient> dr(new ObserverDeathRecipient(observer, this));
102         if (!observer->AsObject()->AddDeathRecipient(dr)) {
103             HILOGE("Failed to link death recipient to observer");
104         }
105         observers_[observer] = dr;
106     }
107 
108     bool isExist = false;
109     for (const auto &it : btServers_) {
110         if (it.first != nullptr && it.first->AsObject() == observer->AsObject()) {
111             HILOGW("btServers_ list already contains given observer");
112             isExist = true;
113             break;
114         }
115     }
116     if (!isExist) {
117         struct RtOberserInfo rtInfo;
118         rtInfo.callbackFunc = func;
119         rtInfo.args = std::make_tuple(args...);
120         btServers_[observer] = rtInfo;
121     }
122 
123     return true;
124 }
125 
126 template <typename T, typename... Args>
Deregister(const sptr<T> & observer)127 bool RemoteObserverList<T, Args...>::Deregister(const sptr<T> &observer)
128 {
129     HILOGI("RemoteObserverList<T, Args...>::Deregister called");
130     for (auto it = observers_.begin(); it != observers_.end();) {
131         if (it->first != nullptr && it->first->AsObject() == observer->AsObject()) {
132             UnregisterInternal(it++);
133         } else {
134             it++;
135         }
136     }
137     HILOGW("Given observer not registered with this list");
138     return false;
139 }
140 
141 template <typename T, typename... Args>
ForEach(const std::function<void (sptr<T>)> & observer)142 void RemoteObserverList<T, Args...>::ForEach(const std::function<void(sptr<T>)> &observer)
143 {
144     std::lock_guard<std::mutex> lock(lock_);
145     for (const auto &it : observers_) {
146         if (it.first != nullptr) {
147             observer(it.first);
148         }
149     }
150 }
151 
152 template <typename T, typename... Args>
ObserverDeathRecipient(const sptr<T> & observer,RemoteObserverList<T,Args...> * owner)153 RemoteObserverList<T, Args...>::ObserverDeathRecipient::ObserverDeathRecipient(
154     const sptr<T> &observer, RemoteObserverList<T, Args...> *owner)
155     : observer_(observer), owner_(owner)
156 {
157     HILOGI("RemoteObserverList<T>::ObserverDeathRecipient::ObserverDeathRecipient called");
158 }
159 
160 template <typename T, typename... Args>
OnRemoteDied(const wptr<IRemoteObject> & object)161 void RemoteObserverList<T, Args...>::ObserverDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &object)
162 {
163     // Remove the observer but no need to call unlinkToDeath.
164     std::lock_guard<std::mutex> lock(owner_->lock_);
165     HILOGD("Enter OnRemoteDied");
166     for (auto it = owner_->btServers_.begin(); it != owner_->btServers_.end();) {
167         if (it->first != nullptr && it->first->AsObject() == object) {
168             if (it->second.callbackFunc) {
169                 std::apply(it->second.callbackFunc, std::tuple_cat(std::make_tuple(it->first), it->second.args));
170             }
171             it = owner_->btServers_.erase(it);
172         } else {
173             it++;
174         }
175     }
176 
177     HILOGI("Callback from dead process unregistered");
178 }
179 
180 template <typename T, typename... Args>
UnregisterInternal(typename ObserverMap::iterator iter)181 bool RemoteObserverList<T, Args...>::UnregisterInternal(typename ObserverMap::iterator iter)
182 {
183     HILOGI("RemoteObserverList<T, Args...>::UnregisterInternal called");
184     sptr<ObserverDeathRecipient> dr = iter->second;
185 
186     if (!dr->GetObserver()->AsObject()->RemoveDeathRecipient(dr)) {
187         HILOGE("Failed to unlink death recipient from observer");
188     }
189 
190     observers_.erase(iter);
191     return true;
192 }
193 }  // namespace Bluetooth
194 }  // namespace OHOS
195 #endif  // REMOTE_OBSERVER_LIST_H
196