1 /*
2 * Copyright (c) 2021 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_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 HILOG_INFO("Dataobs Manager Service has already started.");
53 return;
54 }
55 if (!Init()) {
56 HILOG_ERROR("failed to init service.");
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 HILOG_ERROR("Init Publish failed!");
64 return;
65 }
66
67 HILOG_INFO("Dataobs Manager Service start success.");
68 }
69
Init()70 bool DataObsMgrService::Init()
71 {
72 handler_ = TaskHandlerWrap::GetFfrtHandler();
73 return true;
74 }
75
OnStop()76 void DataObsMgrService::OnStop()
77 {
78 HILOG_INFO("stop service");
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 HILOG_ERROR("dataObserver is nullptr, uri:%{public}s", CommonUtils::Anonymous(uri.ToString()).c_str());
92 return DATA_OBSERVER_IS_NULL;
93 }
94
95 if (dataObsMgrInner_ == nullptr) {
96 HILOG_ERROR("dataObsMgrInner_ is nullptr, uri:%{public}s", CommonUtils::Anonymous(uri.ToString()).c_str());
97 return DATAOBS_SERVICE_INNER_IS_NULL;
98 }
99
100 int status;
101 if (const_cast<Uri &>(uri).GetScheme() == SHARE_PREFERENCES) {
102 status = dataObsMgrInnerPref_->HandleRegisterObserver(uri, dataObserver);
103 } else {
104 status = dataObsMgrInner_->HandleRegisterObserver(uri, dataObserver);
105 }
106
107 if (status != NO_ERROR) {
108 HILOG_ERROR("Observer register failed: %{public}d, uri:%{public}s", status,
109 CommonUtils::Anonymous(uri.ToString()).c_str());
110 return status;
111 }
112 return NO_ERROR;
113 }
114
UnregisterObserver(const Uri & uri,sptr<IDataAbilityObserver> dataObserver)115 int DataObsMgrService::UnregisterObserver(const Uri &uri, sptr<IDataAbilityObserver> dataObserver)
116 {
117 if (dataObserver == nullptr) {
118 HILOG_ERROR("dataObserver is nullptr, uri:%{public}s", CommonUtils::Anonymous(uri.ToString()).c_str());
119 return DATA_OBSERVER_IS_NULL;
120 }
121
122 if (dataObsMgrInner_ == nullptr) {
123 HILOG_ERROR("dataObsMgrInner_ is nullptr, uri:%{public}s", CommonUtils::Anonymous(uri.ToString()).c_str());
124 return DATAOBS_SERVICE_INNER_IS_NULL;
125 }
126
127 int status;
128 if (const_cast<Uri &>(uri).GetScheme() == SHARE_PREFERENCES) {
129 status = dataObsMgrInnerPref_->HandleUnregisterObserver(uri, dataObserver);
130 } else {
131 status = dataObsMgrInner_->HandleUnregisterObserver(uri, dataObserver);
132 }
133
134 if (status != NO_ERROR) {
135 HILOG_ERROR("Observer unregister failed: %{public}d, uri:%{public}s", status,
136 CommonUtils::Anonymous(uri.ToString()).c_str());
137 return status;
138 }
139 return NO_ERROR;
140 }
141
NotifyChange(const Uri & uri)142 int DataObsMgrService::NotifyChange(const Uri &uri)
143 {
144 if (handler_ == nullptr) {
145 HILOG_ERROR("handler is nullptr, uri:%{public}s", CommonUtils::Anonymous(uri.ToString()).c_str());
146 return DATAOBS_SERVICE_HANDLER_IS_NULL;
147 }
148
149 if (dataObsMgrInner_ == nullptr || dataObsMgrInnerExt_ == nullptr || dataObsMgrInnerPref_ == nullptr) {
150 HILOG_ERROR("dataObsMgr is nullptr, uri:%{public}s", CommonUtils::Anonymous(uri.ToString()).c_str());
151 return DATAOBS_SERVICE_INNER_IS_NULL;
152 }
153
154 {
155 std::lock_guard<ffrt::mutex> lck(taskCountMutex_);
156 if (taskCount_ >= TASK_COUNT_MAX) {
157 HILOG_ERROR("The number of task has reached the upper limit, uri:%{public}s",
158 CommonUtils::Anonymous(uri.ToString()).c_str());
159 return DATAOBS_SERVICE_TASK_LIMMIT;
160 }
161 ++taskCount_;
162 }
163
164 ChangeInfo changeInfo = { ChangeInfo::ChangeType::OTHER, { uri } };
165 handler_->SubmitTask([this, uri, changeInfo]() {
166 if (const_cast<Uri &>(uri).GetScheme() == SHARE_PREFERENCES) {
167 dataObsMgrInnerPref_->HandleNotifyChange(uri);
168 } else {
169 dataObsMgrInner_->HandleNotifyChange(uri);
170 dataObsMgrInnerExt_->HandleNotifyChange(changeInfo);
171 }
172 std::lock_guard<ffrt::mutex> lck(taskCountMutex_);
173 --taskCount_;
174 });
175
176 return NO_ERROR;
177 }
178
RegisterObserverExt(const Uri & uri,sptr<IDataAbilityObserver> dataObserver,bool isDescendants)179 Status DataObsMgrService::RegisterObserverExt(const Uri &uri, sptr<IDataAbilityObserver> dataObserver,
180 bool isDescendants)
181 {
182 if (dataObserver == nullptr) {
183 HILOG_ERROR("dataObserver is nullptr, uri:%{public}s, isDescendants:%{public}d",
184 CommonUtils::Anonymous(uri.ToString()).c_str(), isDescendants);
185 return DATA_OBSERVER_IS_NULL;
186 }
187
188 if (dataObsMgrInnerExt_ == nullptr) {
189 HILOG_ERROR("dataObsMgrInner_ is nullptr, uri:%{public}s, isDescendants:%{public}d",
190 CommonUtils::Anonymous(uri.ToString()).c_str(), isDescendants);
191 return DATAOBS_SERVICE_INNER_IS_NULL;
192 }
193
194 auto innerUri = uri;
195 return dataObsMgrInnerExt_->HandleRegisterObserver(innerUri, dataObserver, isDescendants);
196 }
197
UnregisterObserverExt(const Uri & uri,sptr<IDataAbilityObserver> dataObserver)198 Status DataObsMgrService::UnregisterObserverExt(const Uri &uri, sptr<IDataAbilityObserver> dataObserver)
199 {
200 if (dataObserver == nullptr) {
201 HILOG_ERROR("dataObserver is nullptr, uri:%{public}s", CommonUtils::Anonymous(uri.ToString()).c_str());
202 return DATA_OBSERVER_IS_NULL;
203 }
204
205 if (dataObsMgrInnerExt_ == nullptr) {
206 HILOG_ERROR("dataObsMgrInner_ is nullptr, uri:%{public}s", CommonUtils::Anonymous(uri.ToString()).c_str());
207 return DATAOBS_SERVICE_INNER_IS_NULL;
208 }
209
210 auto innerUri = uri;
211 return dataObsMgrInnerExt_->HandleUnregisterObserver(innerUri, dataObserver);
212 }
213
UnregisterObserverExt(sptr<IDataAbilityObserver> dataObserver)214 Status DataObsMgrService::UnregisterObserverExt(sptr<IDataAbilityObserver> dataObserver)
215 {
216 if (dataObserver == nullptr) {
217 HILOG_ERROR("dataObserver is nullptr");
218 return DATA_OBSERVER_IS_NULL;
219 }
220
221 if (dataObsMgrInnerExt_ == nullptr) {
222 HILOG_ERROR("dataObsMgrInner_ is nullptr");
223 return DATAOBS_SERVICE_INNER_IS_NULL;
224 }
225
226 return dataObsMgrInnerExt_->HandleUnregisterObserver(dataObserver);
227 }
228
DeepCopyChangeInfo(const ChangeInfo & src,ChangeInfo & dst) const229 Status DataObsMgrService::DeepCopyChangeInfo(const ChangeInfo &src, ChangeInfo &dst) const
230 {
231 dst = src;
232 if (dst.size_ == 0) {
233 return SUCCESS;
234 }
235 dst.data_ = new (std::nothrow) uint8_t[dst.size_];
236 if (dst.data_ == nullptr) {
237 return DATAOBS_SERVICE_INNER_IS_NULL;
238 }
239
240 errno_t ret = memcpy_s(dst.data_, dst.size_, src.data_, src.size_);
241 if (ret != EOK) {
242 delete [] static_cast<uint8_t *>(dst.data_);
243 dst.data_ = nullptr;
244 return DATAOBS_SERVICE_INNER_IS_NULL;
245 }
246 return SUCCESS;
247 }
248
NotifyChangeExt(const ChangeInfo & changeInfo)249 Status DataObsMgrService::NotifyChangeExt(const ChangeInfo &changeInfo)
250 {
251 if (handler_ == nullptr) {
252 HILOG_ERROR("handler is nullptr");
253 return DATAOBS_SERVICE_HANDLER_IS_NULL;
254 }
255
256 if (dataObsMgrInner_ == nullptr || dataObsMgrInnerExt_ == nullptr) {
257 HILOG_ERROR("dataObsMgrInner_:%{public}d or dataObsMgrInnerExt_ is nullptr", dataObsMgrInner_ == nullptr);
258 return DATAOBS_SERVICE_INNER_IS_NULL;
259 }
260 ChangeInfo changes;
261 Status result = DeepCopyChangeInfo(changeInfo, changes);
262 if (result != SUCCESS) {
263 HILOG_ERROR("copy data failed, changeType:%{public}ud, num of uris:%{public}zu, data is "
264 "nullptr:%{public}d, size:%{public}ud",
265 changeInfo.changeType_, changeInfo.uris_.size(), changeInfo.data_ == nullptr, changeInfo.size_);
266 return result;
267 }
268
269 {
270 std::lock_guard<ffrt::mutex> lck(taskCountMutex_);
271 if (taskCount_ >= TASK_COUNT_MAX) {
272 HILOG_ERROR("The number of task has reached the upper limit, changeType:%{public}ud, num of "
273 "uris:%{public}zu, data is nullptr:%{public}d, size:%{public}ud",
274 changeInfo.changeType_, changeInfo.uris_.size(), changeInfo.data_ == nullptr, changeInfo.size_);
275 return DATAOBS_SERVICE_TASK_LIMMIT;
276 }
277 ++taskCount_;
278 }
279
280 handler_->SubmitTask([this, changes]() {
281 dataObsMgrInnerExt_->HandleNotifyChange(changes);
282 for (auto &uri : changes.uris_) {
283 dataObsMgrInner_->HandleNotifyChange(uri);
284 }
285 delete [] static_cast<uint8_t *>(changes.data_);
286 std::lock_guard<ffrt::mutex> lck(taskCountMutex_);
287 --taskCount_;
288 });
289 return SUCCESS;
290 }
291
Dump(int fd,const std::vector<std::u16string> & args)292 int DataObsMgrService::Dump(int fd, const std::vector<std::u16string>& args)
293 {
294 std::string result;
295 Dump(args, result);
296 int ret = dprintf(fd, "%s\n", result.c_str());
297 if (ret < 0) {
298 HILOG_ERROR("%{public}s, dprintf error.", __func__);
299 return DATAOBS_HIDUMP_ERROR;
300 }
301 return SUCCESS;
302 }
303
Dump(const std::vector<std::u16string> & args,std::string & result) const304 void DataObsMgrService::Dump(const std::vector<std::u16string>& args, std::string& result) const
305 {
306 auto size = args.size();
307 if (size == 0) {
308 ShowHelp(result);
309 return;
310 }
311
312 std::string optionKey = Str16ToStr8(args[0]);
313 if (optionKey != "-h") {
314 result.append("error: unkown option.\n");
315 }
316 ShowHelp(result);
317 }
318
ShowHelp(std::string & result) const319 void DataObsMgrService::ShowHelp(std::string& result) const
320 {
321 result.append("Usage:\n")
322 .append("-h ")
323 .append("help text for the tool\n");
324 }
325 } // namespace AAFwk
326 } // namespace OHOS
327