1 /*
2 * Copyright (c) 2021-2025 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_pref.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
DataObsMgrInnerPref()25 DataObsMgrInnerPref::DataObsMgrInnerPref() {}
26
~DataObsMgrInnerPref()27 DataObsMgrInnerPref::~DataObsMgrInnerPref() {}
28
HandleRegisterObserver(const Uri & uri,struct ObserverNode observerNode)29 int DataObsMgrInnerPref::HandleRegisterObserver(const Uri &uri, struct ObserverNode observerNode)
30 {
31 std::lock_guard<ffrt::mutex> lock(preferenceMutex_);
32
33 auto [obsPair, flag] = observers_.try_emplace(uri.ToString(), std::list<struct ObserverNode>());
34 if (!flag && obsPair->second.size() >= OBS_ALL_NUM_MAX) {
35 TAG_LOGE(AAFwkTag::DBOBSMGR,
36 "subscribers num:%{public}s maxed",
37 CommonUtils::Anonymous(uri.ToString()).c_str());
38 return DATAOBS_SERVICE_OBS_LIMMIT;
39 }
40
41 uint32_t tokenCount = 0;
42 for (auto obs = obsPair->second.begin(); obs != obsPair->second.end(); obs++) {
43 if ((*obs).observer_->AsObject() == observerNode.observer_->AsObject()) {
44 TAG_LOGE(AAFwkTag::DBOBSMGR, "registered obs:%{public}s",
45 CommonUtils::Anonymous(uri.ToString()).c_str());
46 return OBS_EXIST;
47 }
48 if ((*obs).tokenId_ == observerNode.tokenId_) {
49 tokenCount++;
50 if (tokenCount > OBS_NUM_MAX) {
51 TAG_LOGE(AAFwkTag::DBOBSMGR, "subscribers num:%{public}s maxed, token:%{public}d",
52 CommonUtils::Anonymous(uri.ToString()).c_str(), observerNode.tokenId_);
53 return DATAOBS_SERVICE_OBS_LIMMIT;
54 }
55 }
56 }
57
58 obsPair->second.push_back(observerNode);
59
60 AddObsDeathRecipient(observerNode.observer_);
61
62 return NO_ERROR;
63 }
64
HandleUnregisterObserver(const Uri & uri,struct ObserverNode observerNode)65 int DataObsMgrInnerPref::HandleUnregisterObserver(const Uri &uri, struct ObserverNode observerNode)
66 {
67 std::lock_guard<ffrt::mutex> lock(preferenceMutex_);
68
69 auto obsPair = observers_.find(uri.ToString());
70 if (obsPair == observers_.end()) {
71 TAG_LOGW(
72 AAFwkTag::DBOBSMGR, "uris no obs:%{public}s", CommonUtils::Anonymous(uri.ToString()).c_str());
73 return NO_OBS_FOR_URI;
74 }
75
76 TAG_LOGD(AAFwkTag::DBOBSMGR, "obs num:%{public}zu:%{public}s", obsPair->second.size(),
77 CommonUtils::Anonymous(uri.ToString()).c_str());
78 auto obs = obsPair->second.begin();
79 for (; obs != obsPair->second.end(); obs++) {
80 if ((*obs).observer_->AsObject() == observerNode.observer_->AsObject()) {
81 break;
82 }
83 }
84 if (obs == obsPair->second.end()) {
85 TAG_LOGW(
86 AAFwkTag::DBOBSMGR, "uris no obs:%{public}s", CommonUtils::Anonymous(uri.ToString()).c_str());
87 return NO_OBS_FOR_URI;
88 }
89 obsPair->second.remove(*obs);
90 if (obsPair->second.empty()) {
91 observers_.erase(obsPair);
92 }
93
94 if (!HaveRegistered(observerNode.observer_)) {
95 RemoveObsDeathRecipient(observerNode.observer_->AsObject());
96 }
97 return NO_ERROR;
98 }
99
HandleNotifyChange(const Uri & uri,int32_t userId)100 int DataObsMgrInnerPref::HandleNotifyChange(const Uri &uri, int32_t userId)
101 {
102 std::list<struct ObserverNode> obsList;
103 std::lock_guard<ffrt::mutex> lock(preferenceMutex_);
104 {
105 std::string uriStr = uri.ToString();
106 size_t pos = uriStr.find('?');
107 if (pos == std::string::npos) {
108 TAG_LOGW(AAFwkTag::DBOBSMGR, "uri missing query:%{public}s",
109 CommonUtils::Anonymous(uriStr).c_str());
110 return INVALID_PARAM;
111 }
112 std::string observerKey = uriStr.substr(0, pos);
113 auto obsPair = observers_.find(observerKey);
114 if (obsPair == observers_.end()) {
115 TAG_LOGD(AAFwkTag::DBOBSMGR, "uri no obs:%{public}s",
116 CommonUtils::Anonymous(uri.ToString()).c_str());
117 return NO_OBS_FOR_URI;
118 }
119 obsList = obsPair->second;
120 }
121
122 for (auto &obs : obsList) {
123 if (obs.observer_ == nullptr) {
124 continue;
125 }
126 if (obs.userId_ != 0 && userId != 0 && obs.userId_ != userId) {
127 TAG_LOGW(AAFwkTag::DBOBSMGR, "Not allow across user notify, %{public}d to %{public}d, %{public}s",
128 userId, obs.userId_, CommonUtils::Anonymous(uri.ToString()).c_str());
129 continue;
130 }
131 obs.observer_->OnChangePreferences(const_cast<Uri &>(uri).GetQuery());
132 }
133
134 TAG_LOGD(AAFwkTag::DBOBSMGR, "uri end:%{public}s,obs num:%{public}zu",
135 CommonUtils::Anonymous(uri.ToString()).c_str(), obsList.size());
136 return NO_ERROR;
137 }
138
AddObsDeathRecipient(sptr<IDataAbilityObserver> dataObserver)139 void DataObsMgrInnerPref::AddObsDeathRecipient(sptr<IDataAbilityObserver> dataObserver)
140 {
141 if ((dataObserver == nullptr) || dataObserver->AsObject() == nullptr) {
142 return;
143 }
144
145 auto it = obsRecipient_.find(dataObserver->AsObject());
146 if (it != obsRecipient_.end()) {
147 TAG_LOGW(AAFwkTag::DBOBSMGR, "called");
148 return;
149 } else {
150 std::weak_ptr<DataObsMgrInnerPref> thisWeakPtr(shared_from_this());
151 sptr<IRemoteObject::DeathRecipient> deathRecipient =
152 new DataObsCallbackRecipient([thisWeakPtr](const wptr<IRemoteObject> &remote) {
153 auto dataObsMgrInner = thisWeakPtr.lock();
154 if (dataObsMgrInner) {
155 dataObsMgrInner->OnCallBackDied(remote);
156 }
157 });
158 if (!dataObserver->AsObject()->AddDeathRecipient(deathRecipient)) {
159 TAG_LOGE(AAFwkTag::DBOBSMGR, "failed");
160 }
161 obsRecipient_.emplace(dataObserver->AsObject(), deathRecipient);
162 }
163 }
164
RemoveObsDeathRecipient(sptr<IRemoteObject> dataObserver)165 void DataObsMgrInnerPref::RemoveObsDeathRecipient(sptr<IRemoteObject> dataObserver)
166 {
167 if (dataObserver == nullptr) {
168 return;
169 }
170
171 auto it = obsRecipient_.find(dataObserver);
172 if (it != obsRecipient_.end()) {
173 it->first->RemoveDeathRecipient(it->second);
174 obsRecipient_.erase(it);
175 return;
176 }
177 }
178
OnCallBackDied(const wptr<IRemoteObject> & remote)179 void DataObsMgrInnerPref::OnCallBackDied(const wptr<IRemoteObject> &remote)
180 {
181 auto dataObserver = remote.promote();
182 if (dataObserver == nullptr) {
183 return;
184 }
185 std::lock_guard<ffrt::mutex> lock(preferenceMutex_);
186
187 if (dataObserver == nullptr) {
188 TAG_LOGE(AAFwkTag::DBOBSMGR, "null dataObserver");
189 return;
190 }
191
192 RemoveObs(dataObserver);
193 }
194
RemoveObs(sptr<IRemoteObject> dataObserver)195 void DataObsMgrInnerPref::RemoveObs(sptr<IRemoteObject> dataObserver)
196 {
197 for (auto iter = observers_.begin(); iter != observers_.end();) {
198 auto &obsList = iter->second;
199 for (auto it = obsList.begin(); it != obsList.end(); it++) {
200 if ((*it).observer_->AsObject() == dataObserver) {
201 TAG_LOGD(AAFwkTag::DBOBSMGR, "erase");
202 obsList.erase(it);
203 break;
204 }
205 }
206 if (obsList.size() == 0) {
207 iter = observers_.erase(iter);
208 } else {
209 iter++;
210 }
211 }
212 RemoveObsDeathRecipient(dataObserver);
213 }
214
HaveRegistered(sptr<IDataAbilityObserver> dataObserver)215 bool DataObsMgrInnerPref::HaveRegistered(sptr<IDataAbilityObserver> dataObserver)
216 {
217 for (auto &[key, value] : observers_) {
218 for (struct ObserverNode& node: value) {
219 if (node.observer_ == dataObserver) {
220 return true;
221 }
222 }
223 }
224 return false;
225 }
226 } // namespace AAFwk
227 } // namespace OHOS
228