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 
16 #include "dataobs_mgr_service.h"
17 
18 #include <functional>
19 #include <memory>
20 #include <string>
21 #include <unistd.h>
22 #include "string_ex.h"
23 
24 #include "dataobs_mgr_errors.h"
25 #include "hilog_tag_wrapper.h"
26 #include "if_system_ability_manager.h"
27 #include "ipc_skeleton.h"
28 #include "system_ability_definition.h"
29 #include "common_utils.h"
30 #include "securec.h"
31 
32 namespace OHOS {
33 namespace AAFwk {
34 const bool REGISTER_RESULT =
35     SystemAbility::MakeAndRegisterAbility(DelayedSingleton<DataObsMgrService>::GetInstance().get());
36 
DataObsMgrService()37 DataObsMgrService::DataObsMgrService()
38     : SystemAbility(DATAOBS_MGR_SERVICE_SA_ID, true),
39       state_(DataObsServiceRunningState::STATE_NOT_START)
40 {
41     dataObsMgrInner_ = std::make_shared<DataObsMgrInner>();
42     dataObsMgrInnerExt_ = std::make_shared<DataObsMgrInnerExt>();
43     dataObsMgrInnerPref_ = std::make_shared<DataObsMgrInnerPref>();
44 }
45 
~DataObsMgrService()46 DataObsMgrService::~DataObsMgrService()
47 {}
48 
OnStart()49 void DataObsMgrService::OnStart()
50 {
51     if (state_ == DataObsServiceRunningState::STATE_RUNNING) {
52         TAG_LOGI(AAFwkTag::DBOBSMGR, "dms started");
53         return;
54     }
55     if (!Init()) {
56         TAG_LOGE(AAFwkTag::DBOBSMGR, "init failed");
57         return;
58     }
59     state_ = DataObsServiceRunningState::STATE_RUNNING;
60     /* Publish service maybe failed, so we need call this function at the last,
61      * so it can't affect the TDD test program */
62     if (!Publish(DelayedSingleton<DataObsMgrService>::GetInstance().get())) {
63         TAG_LOGE(AAFwkTag::DBOBSMGR, "publish init failed");
64         return;
65     }
66 
67     TAG_LOGI(AAFwkTag::DBOBSMGR, "dms called");
68 }
69 
Init()70 bool DataObsMgrService::Init()
71 {
72     handler_ = TaskHandlerWrap::GetFfrtHandler();
73     return true;
74 }
75 
OnStop()76 void DataObsMgrService::OnStop()
77 {
78     TAG_LOGI(AAFwkTag::DBOBSMGR, "stop");
79     handler_.reset();
80     state_ = DataObsServiceRunningState::STATE_NOT_START;
81 }
82 
QueryServiceState() const83 DataObsServiceRunningState DataObsMgrService::QueryServiceState() const
84 {
85     return state_;
86 }
87 
RegisterObserver(const Uri & uri,sptr<IDataAbilityObserver> dataObserver)88 int DataObsMgrService::RegisterObserver(const Uri &uri, sptr<IDataAbilityObserver> dataObserver)
89 {
90     if (dataObserver == nullptr) {
91         TAG_LOGE(AAFwkTag::DBOBSMGR, "null dataObserver, uri:%{public}s",
92             CommonUtils::Anonymous(uri.ToString()).c_str());
93         return DATA_OBSERVER_IS_NULL;
94     }
95 
96     if (dataObsMgrInner_ == nullptr) {
97         TAG_LOGE(AAFwkTag::DBOBSMGR, "null dataObsMgrInner, uri:%{public}s",
98             CommonUtils::Anonymous(uri.ToString()).c_str());
99         return DATAOBS_SERVICE_INNER_IS_NULL;
100     }
101 
102     int status;
103     if (const_cast<Uri &>(uri).GetScheme() == SHARE_PREFERENCES) {
104         status = dataObsMgrInnerPref_->HandleRegisterObserver(uri, dataObserver);
105     } else {
106         status = dataObsMgrInner_->HandleRegisterObserver(uri, dataObserver);
107     }
108 
109     if (status != NO_ERROR) {
110         TAG_LOGE(AAFwkTag::DBOBSMGR, "register failed:%{public}d, uri:%{public}s", status,
111             CommonUtils::Anonymous(uri.ToString()).c_str());
112         return status;
113     }
114     return NO_ERROR;
115 }
116 
UnregisterObserver(const Uri & uri,sptr<IDataAbilityObserver> dataObserver)117 int DataObsMgrService::UnregisterObserver(const Uri &uri, sptr<IDataAbilityObserver> dataObserver)
118 {
119     if (dataObserver == nullptr) {
120         TAG_LOGE(AAFwkTag::DBOBSMGR, "null dataObserver, uri:%{public}s",
121             CommonUtils::Anonymous(uri.ToString()).c_str());
122         return DATA_OBSERVER_IS_NULL;
123     }
124 
125     if (dataObsMgrInner_ == nullptr) {
126         TAG_LOGE(AAFwkTag::DBOBSMGR, "null dataObsMgrInner, uri:%{public}s",
127             CommonUtils::Anonymous(uri.ToString()).c_str());
128         return DATAOBS_SERVICE_INNER_IS_NULL;
129     }
130 
131     int status;
132     if (const_cast<Uri &>(uri).GetScheme() == SHARE_PREFERENCES) {
133         status = dataObsMgrInnerPref_->HandleUnregisterObserver(uri, dataObserver);
134     } else {
135         status = dataObsMgrInner_->HandleUnregisterObserver(uri, dataObserver);
136     }
137 
138     if (status != NO_ERROR) {
139         TAG_LOGE(AAFwkTag::DBOBSMGR, "unregister failed:%{public}d, uri:%{public}s", status,
140             CommonUtils::Anonymous(uri.ToString()).c_str());
141         return status;
142     }
143     return NO_ERROR;
144 }
145 
NotifyChange(const Uri & uri)146 int DataObsMgrService::NotifyChange(const Uri &uri)
147 {
148     if (handler_ == nullptr) {
149         TAG_LOGE(
150             AAFwkTag::DBOBSMGR, "null handler, uri:%{public}s", CommonUtils::Anonymous(uri.ToString()).c_str());
151         return DATAOBS_SERVICE_HANDLER_IS_NULL;
152     }
153 
154     if (dataObsMgrInner_ == nullptr || dataObsMgrInnerExt_ == nullptr || dataObsMgrInnerPref_ == nullptr) {
155         TAG_LOGE(AAFwkTag::DBOBSMGR, "null dataObsMgr, uri:%{public}s",
156             CommonUtils::Anonymous(uri.ToString()).c_str());
157         return DATAOBS_SERVICE_INNER_IS_NULL;
158     }
159 
160     {
161         std::lock_guard<ffrt::mutex> lck(taskCountMutex_);
162         if (taskCount_ >= TASK_COUNT_MAX) {
163             TAG_LOGE(AAFwkTag::DBOBSMGR, "task num reached limit, uri:%{public}s",
164                 CommonUtils::Anonymous(uri.ToString()).c_str());
165             return DATAOBS_SERVICE_TASK_LIMMIT;
166         }
167         ++taskCount_;
168     }
169 
170     ChangeInfo changeInfo = { ChangeInfo::ChangeType::OTHER, { uri } };
171     handler_->SubmitTask([this, uri, changeInfo]() {
172         if (const_cast<Uri &>(uri).GetScheme() == SHARE_PREFERENCES) {
173             dataObsMgrInnerPref_->HandleNotifyChange(uri);
174         } else {
175             dataObsMgrInner_->HandleNotifyChange(uri);
176             dataObsMgrInnerExt_->HandleNotifyChange(changeInfo);
177         }
178         std::lock_guard<ffrt::mutex> lck(taskCountMutex_);
179         --taskCount_;
180     });
181 
182     return NO_ERROR;
183 }
184 
RegisterObserverExt(const Uri & uri,sptr<IDataAbilityObserver> dataObserver,bool isDescendants)185 Status DataObsMgrService::RegisterObserverExt(const Uri &uri, sptr<IDataAbilityObserver> dataObserver,
186     bool isDescendants)
187 {
188     if (dataObserver == nullptr) {
189         TAG_LOGE(AAFwkTag::DBOBSMGR, "null dataObserver, uri:%{public}s, isDescendants:%{public}d",
190             CommonUtils::Anonymous(uri.ToString()).c_str(), isDescendants);
191         return DATA_OBSERVER_IS_NULL;
192     }
193 
194     if (dataObsMgrInnerExt_ == nullptr) {
195         TAG_LOGE(AAFwkTag::DBOBSMGR, "null dataObsMgrInner, uri:%{public}s, isDescendants:%{public}d",
196             CommonUtils::Anonymous(uri.ToString()).c_str(), isDescendants);
197         return DATAOBS_SERVICE_INNER_IS_NULL;
198     }
199 
200     auto innerUri = uri;
201     return dataObsMgrInnerExt_->HandleRegisterObserver(innerUri, dataObserver, isDescendants);
202 }
203 
UnregisterObserverExt(const Uri & uri,sptr<IDataAbilityObserver> dataObserver)204 Status DataObsMgrService::UnregisterObserverExt(const Uri &uri, sptr<IDataAbilityObserver> dataObserver)
205 {
206     if (dataObserver == nullptr) {
207         TAG_LOGE(AAFwkTag::DBOBSMGR, "null dataObserver, uri:%{public}s",
208             CommonUtils::Anonymous(uri.ToString()).c_str());
209         return DATA_OBSERVER_IS_NULL;
210     }
211 
212     if (dataObsMgrInnerExt_ == nullptr) {
213         TAG_LOGE(AAFwkTag::DBOBSMGR, "null dataObsMgrInner, uri:%{public}s",
214             CommonUtils::Anonymous(uri.ToString()).c_str());
215         return DATAOBS_SERVICE_INNER_IS_NULL;
216     }
217 
218     auto innerUri = uri;
219     return dataObsMgrInnerExt_->HandleUnregisterObserver(innerUri, dataObserver);
220 }
221 
UnregisterObserverExt(sptr<IDataAbilityObserver> dataObserver)222 Status DataObsMgrService::UnregisterObserverExt(sptr<IDataAbilityObserver> dataObserver)
223 {
224     if (dataObserver == nullptr) {
225         TAG_LOGE(AAFwkTag::DBOBSMGR, "null dataObserver");
226         return DATA_OBSERVER_IS_NULL;
227     }
228 
229     if (dataObsMgrInnerExt_ == nullptr) {
230         TAG_LOGE(AAFwkTag::DBOBSMGR, "null dataObsMgrInner");
231         return DATAOBS_SERVICE_INNER_IS_NULL;
232     }
233 
234     return dataObsMgrInnerExt_->HandleUnregisterObserver(dataObserver);
235 }
236 
DeepCopyChangeInfo(const ChangeInfo & src,ChangeInfo & dst) const237 Status DataObsMgrService::DeepCopyChangeInfo(const ChangeInfo &src, ChangeInfo &dst) const
238 {
239     dst = src;
240     if (dst.size_ == 0) {
241         return SUCCESS;
242     }
243     dst.data_ = new (std::nothrow) uint8_t[dst.size_];
244     if (dst.data_ == nullptr) {
245         return DATAOBS_SERVICE_INNER_IS_NULL;
246     }
247 
248     errno_t ret = memcpy_s(dst.data_, dst.size_, src.data_, src.size_);
249     if (ret != EOK) {
250         delete [] static_cast<uint8_t *>(dst.data_);
251         dst.data_ = nullptr;
252         return DATAOBS_SERVICE_INNER_IS_NULL;
253     }
254     return SUCCESS;
255 }
256 
NotifyChangeExt(const ChangeInfo & changeInfo)257 Status DataObsMgrService::NotifyChangeExt(const ChangeInfo &changeInfo)
258 {
259     if (handler_ == nullptr) {
260         TAG_LOGE(AAFwkTag::DBOBSMGR, "null handler");
261         return DATAOBS_SERVICE_HANDLER_IS_NULL;
262     }
263 
264     if (dataObsMgrInner_ == nullptr || dataObsMgrInnerExt_ == nullptr) {
265         TAG_LOGE(AAFwkTag::DBOBSMGR, "dataObsMgrInner_:%{public}d or null dataObsMgrInnerExt",
266             dataObsMgrInner_ == nullptr);
267         return DATAOBS_SERVICE_INNER_IS_NULL;
268     }
269     ChangeInfo changes;
270     Status result = DeepCopyChangeInfo(changeInfo, changes);
271     if (result != SUCCESS) {
272         TAG_LOGE(AAFwkTag::DBOBSMGR,
273             "copy data failed, changeType:%{public}ud,uris num:%{public}zu, "
274             "null data:%{public}d, size:%{public}ud",
275             changeInfo.changeType_, changeInfo.uris_.size(), changeInfo.data_ == nullptr, changeInfo.size_);
276         return result;
277     }
278 
279     {
280         std::lock_guard<ffrt::mutex> lck(taskCountMutex_);
281         if (taskCount_ >= TASK_COUNT_MAX) {
282             TAG_LOGE(AAFwkTag::DBOBSMGR,
283                 "task num maxed, changeType:%{public}ud,"
284                 "uris num:%{public}zu, null data:%{public}d, size:%{public}ud",
285                 changeInfo.changeType_, changeInfo.uris_.size(), changeInfo.data_ == nullptr, changeInfo.size_);
286             return DATAOBS_SERVICE_TASK_LIMMIT;
287         }
288         ++taskCount_;
289     }
290 
291     handler_->SubmitTask([this, changes]() {
292         dataObsMgrInnerExt_->HandleNotifyChange(changes);
293         for (auto &uri : changes.uris_) {
294             dataObsMgrInner_->HandleNotifyChange(uri);
295         }
296         delete [] static_cast<uint8_t *>(changes.data_);
297         std::lock_guard<ffrt::mutex> lck(taskCountMutex_);
298         --taskCount_;
299     });
300     return SUCCESS;
301 }
302 
Dump(int fd,const std::vector<std::u16string> & args)303 int DataObsMgrService::Dump(int fd, const std::vector<std::u16string>& args)
304 {
305     std::string result;
306     Dump(args, result);
307     int ret = dprintf(fd, "%s\n", result.c_str());
308     if (ret < 0) {
309         TAG_LOGE(AAFwkTag::DBOBSMGR, "dprintf error");
310         return DATAOBS_HIDUMP_ERROR;
311     }
312     return SUCCESS;
313 }
314 
Dump(const std::vector<std::u16string> & args,std::string & result) const315 void DataObsMgrService::Dump(const std::vector<std::u16string>& args, std::string& result) const
316 {
317     auto size = args.size();
318     if (size == 0) {
319         ShowHelp(result);
320         return;
321     }
322 
323     std::string optionKey = Str16ToStr8(args[0]);
324     if (optionKey != "-h") {
325         result.append("error: unkown option.\n");
326     }
327     ShowHelp(result);
328 }
329 
ShowHelp(std::string & result) const330 void DataObsMgrService::ShowHelp(std::string& result) const
331 {
332     result.append("Usage:\n")
333         .append("-h                          ")
334         .append("help text for the tool\n");
335 }
336 }  // namespace AAFwk
337 }  // namespace OHOS
338