• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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