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