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 #include "dataobs_mgr_inner_ext.h"
16
17 #include "data_ability_observer_stub.h"
18 #include "dataobs_mgr_errors.h"
19 #include "hilog_wrapper.h"
20 #include "common_utils.h"
21
22 namespace OHOS {
23 namespace AAFwk {
24
DataObsMgrInnerExt()25 DataObsMgrInnerExt::DataObsMgrInnerExt() : root_(std::make_shared<Node>("root")) {}
26
~DataObsMgrInnerExt()27 DataObsMgrInnerExt::~DataObsMgrInnerExt() {}
28
HandleRegisterObserver(Uri & uri,sptr<IDataAbilityObserver> dataObserver,bool isDescendants)29 Status DataObsMgrInnerExt::HandleRegisterObserver(Uri &uri, sptr<IDataAbilityObserver> dataObserver, bool isDescendants)
30 {
31 if (dataObserver->AsObject() == nullptr) {
32 return DATA_OBSERVER_IS_NULL;
33 }
34 std::lock_guard<ffrt::mutex> lock(nodeMutex_);
35 auto deathRecipientRef = AddObsDeathRecipient(dataObserver->AsObject());
36 if (deathRecipientRef == nullptr) {
37 return DATAOBS_SERVICE_OBS_LIMMIT;
38 }
39
40 std::vector<std::string> path = { uri.GetScheme(), uri.GetAuthority() };
41 uri.GetPathSegments(path);
42 if (root_ != nullptr && !root_->AddObserver(path, 0, Entry(dataObserver, deathRecipientRef, isDescendants))) {
43 HILOG_ERROR("The number of subscribers for this uri : %{public}s has reached the upper limit.",
44 CommonUtils::Anonymous(uri.ToString()).c_str());
45 RemoveObsDeathRecipient(dataObserver->AsObject());
46 return DATAOBS_SERVICE_OBS_LIMMIT;
47 }
48 return SUCCESS;
49 }
50
HandleUnregisterObserver(Uri & uri,sptr<IDataAbilityObserver> dataObserver)51 Status DataObsMgrInnerExt::HandleUnregisterObserver(Uri &uri, sptr<IDataAbilityObserver> dataObserver)
52 {
53 if (dataObserver->AsObject() == nullptr) {
54 HILOG_ERROR("dataObserver is null, uri : %{public}s has reached the upper limit.",
55 CommonUtils::Anonymous(uri.ToString()).c_str());
56 return DATA_OBSERVER_IS_NULL;
57 }
58 std::lock_guard<ffrt::mutex> lock(nodeMutex_);
59 std::vector<std::string> path = { uri.GetScheme(), uri.GetAuthority() };
60 uri.GetPathSegments(path);
61 if (root_ != nullptr) {
62 root_->RemoveObserver(path, 0, dataObserver);
63 }
64 RemoveObsDeathRecipient(dataObserver->AsObject());
65 return SUCCESS;
66 }
67
HandleUnregisterObserver(sptr<IDataAbilityObserver> dataObserver)68 Status DataObsMgrInnerExt::HandleUnregisterObserver(sptr<IDataAbilityObserver> dataObserver)
69 {
70 if (dataObserver->AsObject() == nullptr) {
71 HILOG_ERROR("dataObserver is null");
72 return DATA_OBSERVER_IS_NULL;
73 }
74 std::lock_guard<ffrt::mutex> lock(nodeMutex_);
75 if (root_ != nullptr) {
76 root_->RemoveObserver(dataObserver);
77 }
78 RemoveObsDeathRecipient(dataObserver->AsObject(), true);
79 return SUCCESS;
80 }
81
HandleNotifyChange(const ChangeInfo & changeInfo)82 Status DataObsMgrInnerExt::HandleNotifyChange(const ChangeInfo &changeInfo)
83 {
84 ObsMap changeRes;
85 std::vector<std::string> path;
86 {
87 std::lock_guard<ffrt::mutex> lock(nodeMutex_);
88 for (auto &uri : changeInfo.uris_) {
89 path.clear();
90 path.emplace_back(uri.GetScheme());
91 path.emplace_back(uri.GetAuthority());
92 uri.GetPathSegments(path);
93 root_->GetObs(path, 0, uri, changeRes);
94 }
95 }
96 if (changeRes.empty()) {
97 HILOG_DEBUG("no obs for this uris, changeType:%{public}ud, num of uris:%{public}zu, data is "
98 "nullptr:%{public}d, size:%{public}ud",
99 changeInfo.changeType_, changeInfo.uris_.size(), changeInfo.data_ == nullptr, changeInfo.size_);
100 return NO_OBS_FOR_URI;
101 }
102 for (const auto &[obs, value] : changeRes) {
103 if (obs != nullptr && !value.empty()) {
104 obs->OnChangeExt({ changeInfo.changeType_, move(value), changeInfo.data_, changeInfo.size_ });
105 }
106 }
107
108 return SUCCESS;
109 }
110
AddObsDeathRecipient(const sptr<IRemoteObject> & dataObserver)111 std::shared_ptr<DataObsMgrInnerExt::DeathRecipientRef> DataObsMgrInnerExt::AddObsDeathRecipient(
112 const sptr<IRemoteObject> &dataObserver)
113 {
114 auto it = obsRecipientRefs.find(dataObserver);
115 if (it != obsRecipientRefs.end()) {
116 if (std::numeric_limits<uint32_t>::max() - 1 < it->second->ref) {
117 HILOG_ERROR("the num of observer reach max limit");
118 return nullptr;
119 }
120 } else {
121 std::weak_ptr<DataObsMgrInnerExt> thisWeakPtr(shared_from_this());
122 sptr<IRemoteObject::DeathRecipient> deathRecipient =
123 new DataObsCallbackRecipient([thisWeakPtr](const wptr<IRemoteObject> &remote) {
124 auto DataObsMgrInnerExt = thisWeakPtr.lock();
125 if (DataObsMgrInnerExt) {
126 DataObsMgrInnerExt->OnCallBackDied(remote);
127 }
128 });
129 dataObserver->AddDeathRecipient(deathRecipient);
130 it = obsRecipientRefs.emplace(dataObserver, std::make_shared<DeathRecipientRef>(deathRecipient)).first;
131 }
132 HILOG_DEBUG("this observer will be added, sum:%{public}ud", it->second->ref.load(std::memory_order_relaxed));
133 return it->second;
134 }
135
RemoveObsDeathRecipient(const sptr<IRemoteObject> & dataObserver,bool isForce)136 void DataObsMgrInnerExt::RemoveObsDeathRecipient(const sptr<IRemoteObject> &dataObserver, bool isForce)
137 {
138 auto it = obsRecipientRefs.find(dataObserver);
139 if (it == obsRecipientRefs.end()) {
140 return;
141 }
142
143 if (isForce || it->second->ref <= 1) {
144 HILOG_DEBUG("this observer deathRecipient will be remove, sum:%{public}ud",
145 it->second->ref.load(std::memory_order_relaxed));
146 dataObserver->RemoveDeathRecipient(it->second->deathRecipient);
147 obsRecipientRefs.erase(it);
148 return;
149 }
150 }
151
OnCallBackDied(const wptr<IRemoteObject> & remote)152 void DataObsMgrInnerExt::OnCallBackDied(const wptr<IRemoteObject> &remote)
153 {
154 HILOG_DEBUG("this observer died");
155 auto dataObserver = remote.promote();
156 if (dataObserver == nullptr) {
157 return;
158 }
159 std::lock_guard<ffrt::mutex> lock(nodeMutex_);
160 if (root_ != nullptr) {
161 root_->RemoveObserver(dataObserver);
162 }
163 RemoveObsDeathRecipient(dataObserver, true);
164 }
165
Node(const std::string & name)166 DataObsMgrInnerExt::Node::Node(const std::string &name) : name_(name) {}
167
GetObs(const std::vector<std::string> & path,uint32_t index,Uri & uri,ObsMap & obsRes)168 void DataObsMgrInnerExt::Node::GetObs(const std::vector<std::string> &path, uint32_t index, Uri &uri, ObsMap &obsRes)
169 {
170 if (path.size() == index) {
171 for (auto entry : entrys_) {
172 obsRes.try_emplace(entry.observer, std::list<Uri>()).first->second.push_back(uri);
173 }
174 return;
175 }
176
177 for (const auto &entry : entrys_) {
178 if (entry.isDescendants) {
179 obsRes.try_emplace(entry.observer, std::list<Uri>()).first->second.push_back(uri);
180 }
181 }
182
183 auto it = childrens_.find(path[index]);
184 if (it == childrens_.end()) {
185 return;
186 }
187 it->second->GetObs(path, ++index, uri, obsRes);
188
189 return;
190 }
191
AddObserver(const std::vector<std::string> & path,uint32_t index,const Entry & entry)192 bool DataObsMgrInnerExt::Node::AddObserver(const std::vector<std::string> &path, uint32_t index, const Entry &entry)
193 {
194 if (path.size() == index) {
195 if (entrys_.size() >= OBS_NUM_MAX) {
196 return false;
197 }
198 entry.deathRecipientRef->ref++;
199 entrys_.emplace_back(entry);
200 return true;
201 }
202 auto it = childrens_.try_emplace(path[index], std::make_shared<Node>(path[index])).first;
203 return it->second->AddObserver(path, ++index, entry);
204 }
205
RemoveObserver(const std::vector<std::string> & path,uint32_t index,sptr<IDataAbilityObserver> dataObserver)206 bool DataObsMgrInnerExt::Node::RemoveObserver(const std::vector<std::string> &path, uint32_t index,
207 sptr<IDataAbilityObserver> dataObserver)
208 {
209 if (index == path.size()) {
210 entrys_.remove_if([dataObserver](const Entry &entry) {
211 if (entry.observer->AsObject() != dataObserver->AsObject()) {
212 return false;
213 }
214 entry.deathRecipientRef->ref--;
215 return true;
216 });
217 return entrys_.empty() && childrens_.empty();
218 }
219 auto child = childrens_.find(path[index]);
220 if (child != childrens_.end() && child->second->RemoveObserver(path, ++index, dataObserver)) {
221 childrens_.erase(child);
222 }
223 return entrys_.empty() && childrens_.empty();
224 }
225
RemoveObserver(sptr<IRemoteObject> dataObserver)226 bool DataObsMgrInnerExt::Node::RemoveObserver(sptr<IRemoteObject> dataObserver)
227 {
228 for (auto child = childrens_.begin(); child != childrens_.end();) {
229 if (child->second->RemoveObserver(dataObserver)) {
230 child = childrens_.erase(child);
231 } else {
232 child++;
233 }
234 }
235 entrys_.remove_if([dataObserver](const Entry &entry) {
236 if (entry.observer->AsObject() != dataObserver) {
237 return false;
238 }
239 entry.deathRecipientRef->ref--;
240 return true;
241 });
242 return entrys_.empty() && childrens_.empty();
243 }
244
RemoveObserver(sptr<IDataAbilityObserver> dataObserver)245 inline bool DataObsMgrInnerExt::Node::RemoveObserver(sptr<IDataAbilityObserver> dataObserver)
246 {
247 auto obs = dataObserver->AsObject();
248 return obs != nullptr && RemoveObserver(obs);
249 }
250
251 } // namespace AAFwk
252 } // namespace OHOS
253