1 /*
2 * Copyright (c) 2022-2023 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 "distributed_notification_manager.h"
17
18 #include <vector>
19
20 #include "ans_inner_errors.h"
21 #include "ans_log_wrapper.h"
22 #include "ans_trace_wrapper.h"
23 #include "distributed_data_define.h"
24
25 namespace OHOS {
26 namespace Notification {
27 namespace {
28 const std::string DELIMITER = "|";
29 } // namespace
30
DistributedNotificationManager()31 DistributedNotificationManager::DistributedNotificationManager()
32 {
33 ANS_LOGI("constructor");
34 distributedQueue_ = std::make_shared<ffrt::queue>("NotificationDistributedMgr");
35
36 DistributedDatabaseCallback::IDatabaseChange databaseCallback = {
37 .OnInsert = std::bind(&DistributedNotificationManager::OnDatabaseInsert,
38 this,
39 std::placeholders::_1,
40 std::placeholders::_2,
41 std::placeholders::_3),
42 .OnUpdate = std::bind(&DistributedNotificationManager::OnDatabaseUpdate,
43 this,
44 std::placeholders::_1,
45 std::placeholders::_2,
46 std::placeholders::_3),
47 .OnDelete = std::bind(&DistributedNotificationManager::OnDatabaseDelete,
48 this,
49 std::placeholders::_1,
50 std::placeholders::_2,
51 std::placeholders::_3),
52 };
53 databaseCb_ = std::make_shared<DistributedDatabaseCallback>(databaseCallback);
54
55 DistributedDeviceCallback::IDeviceChange deviceCallback = {
56 .OnConnected = std::bind(&DistributedNotificationManager::OnDeviceConnected, this, std::placeholders::_1),
57 .OnDisconnected = std::bind(&DistributedNotificationManager::OnDeviceDisconnected, this, std::placeholders::_1),
58 };
59 deviceCb_ = std::make_shared<DistributedDeviceCallback>(deviceCallback);
60 database_ = std::make_shared<DistributedDatabase>(databaseCb_, deviceCb_);
61 }
62
~DistributedNotificationManager()63 DistributedNotificationManager::~DistributedNotificationManager()
64 {
65 ANS_LOGI("deconstructor");
66 std::lock_guard<ffrt::mutex> lock(callbackMutex_);
67 callback_ = {};
68 }
69
ResetFfrtQueue()70 void DistributedNotificationManager::ResetFfrtQueue()
71 {
72 if (distributedQueue_ != nullptr) {
73 distributedQueue_.reset();
74 }
75 }
76
GenerateDistributedKey(const std::string & deviceId,const std::string & bundleName,const std::string & label,int32_t id,std::string & key)77 void DistributedNotificationManager::GenerateDistributedKey(
78 const std::string &deviceId, const std::string &bundleName, const std::string &label, int32_t id, std::string &key)
79 {
80 key = deviceId + DELIMITER + bundleName + DELIMITER + label + DELIMITER + ToString(id);
81 }
82
GenerateLocalDistributedKey(const std::string & bundleName,const std::string & label,int32_t id,std::string & key)83 bool DistributedNotificationManager::GenerateLocalDistributedKey(
84 const std::string &bundleName, const std::string &label, int32_t id, std::string &key)
85 {
86 std::string deviceId;
87 if (database_ == nullptr) {
88 ANS_LOGE("database_ is invalid.");
89 return false;
90 }
91 if (!database_->GetLocalDeviceId(deviceId)) {
92 return false;
93 }
94
95 GenerateDistributedKey(deviceId, bundleName, label, id, key);
96 return true;
97 }
98
ResolveDistributedKey(const std::string & key,ResolveKey & resolveKey)99 bool DistributedNotificationManager::ResolveDistributedKey(const std::string &key, ResolveKey &resolveKey)
100 {
101 std::size_t deviceIdPosition = 0;
102 std::size_t deviceIdEndPosition = key.find(DELIMITER, deviceIdPosition);
103 if (deviceIdEndPosition == std::string::npos) {
104 return false;
105 }
106 std::size_t bundleNamePosition = deviceIdEndPosition + DELIMITER.size();
107 std::size_t bundleNameEndPosition = key.find(DELIMITER, bundleNamePosition);
108 if (bundleNameEndPosition == std::string::npos) {
109 return false;
110 }
111 std::size_t labelPosition = bundleNameEndPosition + DELIMITER.size();
112 std::size_t labelEndPosition = key.find_last_of(DELIMITER) - DELIMITER.size() + 1;
113 if (labelEndPosition < labelPosition) {
114 return false;
115 }
116 std::size_t idPosition = key.find_last_of(DELIMITER) + DELIMITER.size();
117
118 resolveKey.deviceId = key.substr(deviceIdPosition, deviceIdEndPosition - deviceIdPosition);
119 resolveKey.bundleName = key.substr(bundleNamePosition, bundleNameEndPosition - bundleNamePosition);
120 resolveKey.label = key.substr(labelPosition, labelEndPosition - labelPosition);
121 resolveKey.id = atoi(&key[idPosition]);
122
123 return true;
124 }
125
CheckDeviceId(const std::string & deviceId,const std::string & key)126 bool DistributedNotificationManager::CheckDeviceId(const std::string &deviceId, const std::string &key)
127 {
128 ResolveKey resolveKey;
129 if (!ResolveDistributedKey(key, resolveKey)) {
130 ANS_LOGE("key <%{public}s> is invalid.", key.c_str());
131 return false;
132 }
133
134 return deviceId == resolveKey.deviceId;
135 }
136
OnDatabaseInsert(const std::string & deviceId,const std::string & key,const std::string & value)137 void DistributedNotificationManager::OnDatabaseInsert(
138 const std::string &deviceId, const std::string &key, const std::string &value)
139 {
140 ANS_LOGD("start");
141 if (distributedQueue_ == nullptr) {
142 ANS_LOGE("Serial queue is nullptr.");
143 return;
144 }
145 distributedQueue_->submit(std::bind([=]() {
146 if (!CheckDeviceId(deviceId, key)) {
147 ANS_LOGD("device id is distinct. deviceId:%{public}s key:%{public}s",
148 StringAnonymous(deviceId).c_str(), key.c_str());
149 }
150
151 ResolveKey resolveKey;
152 if (!ResolveDistributedKey(key, resolveKey)) {
153 ANS_LOGE("key <%{public}s> is invalidity.", key.c_str());
154 return;
155 }
156
157 sptr<NotificationRequest> request =
158 NotificationJsonConverter::ConvertFromJsonString<NotificationRequest>(value);
159 if (request == nullptr) {
160 ANS_LOGE("convert json to request failed. key:%{public}s", key.c_str());
161 return;
162 }
163
164 PublishCallback(resolveKey.deviceId, resolveKey.bundleName, request);
165 }));
166 }
167
OnDatabaseUpdate(const std::string & deviceId,const std::string & key,const std::string & value)168 void DistributedNotificationManager::OnDatabaseUpdate(
169 const std::string &deviceId, const std::string &key, const std::string &value)
170 {
171 ANS_LOGD("start");
172 if (distributedQueue_ == nullptr) {
173 ANS_LOGE("Serial queue is invalid.");
174 return;
175 }
176 ffrt::task_handle handler = distributedQueue_->submit_h(std::bind([=]() {
177 if (!CheckDeviceId(deviceId, key)) {
178 ANS_LOGD("device id are not the same. deviceId:%{public}s key:%{public}s",
179 StringAnonymous(deviceId).c_str(), key.c_str());
180 }
181
182 ResolveKey resolveKey;
183 if (!ResolveDistributedKey(key, resolveKey)) {
184 ANS_LOGE("key <%{public}s> is invalid.", key.c_str());
185 return;
186 }
187
188 sptr<NotificationRequest> request =
189 NotificationJsonConverter::ConvertFromJsonString<NotificationRequest>(value);
190 if (request == nullptr) {
191 ANS_LOGE("convert json to request failed. key:%{public}s", key.c_str());
192 return;
193 }
194
195 UpdateCallback(resolveKey.deviceId, resolveKey.bundleName, request);
196 }));
197 }
198
OnDatabaseDelete(const std::string & deviceId,const std::string & key,const std::string & value)199 void DistributedNotificationManager::OnDatabaseDelete(
200 const std::string &deviceId, const std::string &key, const std::string &value)
201 {
202 ANS_LOGD("start");
203 if (distributedQueue_ == nullptr) {
204 ANS_LOGE("Serial queue is invalid.");
205 return;
206 }
207 distributedQueue_->submit(std::bind([=]() {
208 if (!CheckDeviceId(deviceId, key)) {
209 ANS_LOGD("device id are not the same. deviceId:%{public}s key:%{public}s",
210 StringAnonymous(deviceId).c_str(), key.c_str());
211 }
212
213 ResolveKey resolveKey;
214 if (!ResolveDistributedKey(key, resolveKey)) {
215 ANS_LOGE("key <%{public}s> is invalid.", key.c_str());
216 return;
217 }
218
219 DeleteCallback(resolveKey.deviceId, resolveKey.bundleName, resolveKey.label, resolveKey.id);
220 }));
221 }
222
OnDeviceConnected(const std::string & deviceId)223 void DistributedNotificationManager::OnDeviceConnected(const std::string &deviceId)
224 {
225 ANS_LOGD("start");
226 if (distributedQueue_ == nullptr) {
227 ANS_LOGE("Serial queue is invalid.");
228 return;
229 }
230 distributedQueue_->submit(std::bind([=]() {
231 if (database_ == nullptr) {
232 ANS_LOGE("OnDeviceConnected failed: database is null");
233 return;
234 }
235 if (!database_->OnDeviceConnected()) {
236 ANS_LOGE("OnDeviceConnected failed.");
237 }
238 }));
239 }
240
OnDeviceDisconnected(const std::string & deviceId)241 void DistributedNotificationManager::OnDeviceDisconnected(const std::string &deviceId)
242 {
243 ANS_LOGD("start");
244 if (distributedQueue_ == nullptr) {
245 ANS_LOGE("Serial queue is invalid.");
246 return;
247 }
248 distributedQueue_->submit(std::bind([=]() {
249 std::string prefixKey = deviceId + DELIMITER;
250 std::vector<DistributedDatabase::Entry> entries;
251 if (database_ == nullptr) {
252 ANS_LOGE("database_ is invalid.");
253 return;
254 }
255 if (!database_->GetEntriesFromDistributedDB(prefixKey, entries)) {
256 ANS_LOGE("GetEntriesFromDistributedDB failed.");
257 return;
258 }
259
260 for (auto index : entries) {
261 ResolveKey resolveKey;
262 if (!ResolveDistributedKey(index.key.ToString(), resolveKey)) {
263 ANS_LOGE("key <%{public}s> is invalid.", index.key.ToString().c_str());
264 continue;
265 }
266
267 DeleteCallback(resolveKey.deviceId, resolveKey.bundleName, resolveKey.label, resolveKey.id);
268 }
269
270 database_->ClearDataByDevice(deviceId);
271
272 std::vector<DistributedDatabase::DeviceInfo> deviceList;
273 if (database_->GetDeviceInfoList(deviceList) == ERR_OK && deviceList.empty()) {
274 database_->RecreateDistributedDB();
275 }
276 }));
277 }
278
PublishCallback(const std::string & deviceId,const std::string & bundleName,sptr<NotificationRequest> & request)279 bool DistributedNotificationManager::PublishCallback(
280 const std::string &deviceId, const std::string &bundleName, sptr<NotificationRequest> &request)
281 {
282 ANS_LOGI("start");
283 std::lock_guard<ffrt::mutex> lock(callbackMutex_);
284 if (callback_.OnPublish) {
285 callback_.OnPublish(deviceId, bundleName, request);
286 }
287 ANS_LOGD("end");
288
289 return true;
290 }
291
UpdateCallback(const std::string & deviceId,const std::string & bundleName,sptr<NotificationRequest> & request)292 bool DistributedNotificationManager::UpdateCallback(
293 const std::string &deviceId, const std::string &bundleName, sptr<NotificationRequest> &request)
294 {
295 ANS_LOGI("start");
296 std::lock_guard<ffrt::mutex> lock(callbackMutex_);
297 if (callback_.OnUpdate) {
298 callback_.OnUpdate(deviceId, bundleName, request);
299 }
300 ANS_LOGD("end");
301
302 return true;
303 }
304
DeleteCallback(const std::string & deviceId,const std::string & bundleName,const std::string & label,int32_t id)305 bool DistributedNotificationManager::DeleteCallback(
306 const std::string &deviceId, const std::string &bundleName, const std::string &label, int32_t id)
307 {
308 ANS_LOGI("start");
309 std::lock_guard<ffrt::mutex> lock(callbackMutex_);
310 if (callback_.OnDelete) {
311 callback_.OnDelete(deviceId, bundleName, label, id);
312 }
313 ANS_LOGD("end");
314
315 return true;
316 }
317
Publish(const std::string & bundleName,const std::string & label,int32_t id,const sptr<NotificationRequest> & request)318 ErrCode DistributedNotificationManager::Publish(
319 const std::string &bundleName, const std::string &label, int32_t id, const sptr<NotificationRequest> &request)
320 {
321 NOTIFICATION_HITRACE(HITRACE_TAG_NOTIFICATION);
322 ANS_LOGD("start");
323 std::string key;
324 if (!GenerateLocalDistributedKey(bundleName, label, id, key)) {
325 ANS_LOGE("Failed to generate distributed key.");
326 return ERR_ANS_DISTRIBUTED_GET_INFO_FAILED;
327 }
328
329 std::string value;
330 if (!NotificationJsonConverter::ConvertToJsonString(request, value)) {
331 ANS_LOGE("convert request to json failed. key:%{public}s", key.c_str());
332 return ERR_ANS_DISTRIBUTED_OPERATION_FAILED;
333 }
334
335 if (database_ == nullptr) {
336 ANS_LOGE("database_ is nullptr.");
337 return ERR_ANS_DISTRIBUTED_OPERATION_FAILED;
338 }
339 if (!database_->PutToDistributedDB(key, value)) {
340 ANS_LOGE("put to distributed DB failed. key:%{public}s", key.c_str());
341 return ERR_ANS_DISTRIBUTED_OPERATION_FAILED;
342 }
343
344 return ERR_OK;
345 }
346
Update(const std::string & bundleName,const std::string & label,int32_t id,const sptr<NotificationRequest> & request)347 ErrCode DistributedNotificationManager::Update(
348 const std::string &bundleName, const std::string &label, int32_t id, const sptr<NotificationRequest> &request)
349 {
350 ANS_LOGD("start");
351 std::string key;
352 if (!GenerateLocalDistributedKey(bundleName, label, id, key)) {
353 ANS_LOGE("Generate distributed key failed.");
354 return ERR_ANS_DISTRIBUTED_GET_INFO_FAILED;
355 }
356
357 std::string value;
358 if (!NotificationJsonConverter::ConvertToJsonString(request, value)) {
359 ANS_LOGE("convert request to json failed. key:%{public}s", key.c_str());
360 return ERR_ANS_DISTRIBUTED_OPERATION_FAILED;
361 }
362
363 if (database_ == nullptr) {
364 ANS_LOGE("database_ is invalid.");
365 return ERR_ANS_DISTRIBUTED_OPERATION_FAILED;
366 }
367 if (!database_->PutToDistributedDB(key, value)) {
368 ANS_LOGE("put to distributed DB failed. key:%{public}s", key.c_str());
369 return ERR_ANS_DISTRIBUTED_OPERATION_FAILED;
370 }
371 return ERR_OK;
372 }
373
Delete(const std::string & bundleName,const std::string & label,int32_t id)374 ErrCode DistributedNotificationManager::Delete(const std::string &bundleName, const std::string &label, int32_t id)
375 {
376 NOTIFICATION_HITRACE(HITRACE_TAG_NOTIFICATION);
377 ANS_LOGD("start");
378 std::string key;
379 if (!GenerateLocalDistributedKey(bundleName, label, id, key)) {
380 ANS_LOGE("Generate distributed key failed.");
381 return ERR_ANS_DISTRIBUTED_GET_INFO_FAILED;
382 }
383
384 if (database_ == nullptr) {
385 ANS_LOGE("database_ is nullptr.");
386 return ERR_ANS_DISTRIBUTED_OPERATION_FAILED;
387 }
388 if (!database_->DeleteToDistributedDB(key)) {
389 ANS_LOGE("Failed to DeleteToDistributedDB. key:%{public}s", key.c_str());
390 return ERR_ANS_DISTRIBUTED_OPERATION_FAILED;
391 }
392 return ERR_OK;
393 }
394
DeleteRemoteNotification(const std::string & deviceId,const std::string & bundleName,const std::string & label,int32_t id)395 ErrCode DistributedNotificationManager::DeleteRemoteNotification(
396 const std::string &deviceId, const std::string &bundleName, const std::string &label, int32_t id)
397 {
398 NOTIFICATION_HITRACE(HITRACE_TAG_NOTIFICATION);
399 ANS_LOGD("start");
400
401 std::string key;
402 GenerateDistributedKey(deviceId, bundleName, label, id, key);
403
404 if (database_ == nullptr) {
405 ANS_LOGE("database_ is invalid.");
406 return ERR_ANS_DISTRIBUTED_OPERATION_FAILED;
407 }
408 if (!database_->DeleteToDistributedDB(key)) {
409 ANS_LOGE("delete to distributed DB failed. key:%{public}s", StringAnonymous(key).c_str());
410 return ERR_ANS_DISTRIBUTED_OPERATION_FAILED;
411 }
412 return ERR_OK;
413 }
414
RegisterCallback(const IDistributedCallback & callback)415 ErrCode DistributedNotificationManager::RegisterCallback(const IDistributedCallback &callback)
416 {
417 ANS_LOGD("start");
418 if (distributedQueue_ == nullptr) {
419 ANS_LOGE("Serial queue is invalid.");
420 return ERR_ANS_INVALID_PARAM;
421 }
422 std::lock_guard<ffrt::mutex> lock(callbackMutex_);
423 callback_ = callback;
424 return ERR_OK;
425 }
426
UngegisterCallback()427 ErrCode DistributedNotificationManager::UngegisterCallback()
428 {
429 ANS_LOGD("start");
430 std::lock_guard<ffrt::mutex> lock(callbackMutex_);
431 callback_ = {};
432 return ERR_OK;
433 }
434
GetCurrentDistributedNotification(std::vector<sptr<NotificationRequest>> & requestList)435 ErrCode DistributedNotificationManager::GetCurrentDistributedNotification(
436 std::vector<sptr<NotificationRequest>> &requestList)
437 {
438 ANS_LOGD("start");
439 std::string prefixKey = "";
440 std::vector<DistributedDatabase::Entry> entries;
441 if (database_ == nullptr) {
442 ANS_LOGE("database_ is invalid.");
443 return ERR_ANS_DISTRIBUTED_OPERATION_FAILED;
444 }
445 if (!database_->GetEntriesFromDistributedDB(prefixKey, entries)) {
446 ANS_LOGE("GetEntriesFromDistributedDB failed.");
447 return ERR_ANS_DISTRIBUTED_OPERATION_FAILED;
448 }
449
450 for (auto index : entries) {
451 ResolveKey resolveKey;
452 if (!ResolveDistributedKey(index.key.ToString(), resolveKey)) {
453 ANS_LOGE("key <%{public}s> is invalid.", index.key.ToString().c_str());
454 continue;
455 }
456
457 sptr<NotificationRequest> request =
458 NotificationJsonConverter::ConvertFromJsonString<NotificationRequest>(index.value.ToString());
459 if (request == nullptr) {
460 ANS_LOGE("convert json to request failed. key:%{public}s", index.key.ToString().c_str());
461 continue;
462 }
463
464 PublishCallback(resolveKey.deviceId, resolveKey.bundleName, request);
465 }
466
467 return ERR_OK;
468 }
469
GetLocalDeviceInfo(DistributedDatabase::DeviceInfo & deviceInfo)470 ErrCode DistributedNotificationManager::GetLocalDeviceInfo(DistributedDatabase::DeviceInfo &deviceInfo)
471 {
472 ANS_LOGD("start");
473 if (database_ == nullptr) {
474 ANS_LOGE("database_ is invalid.");
475 return ERR_ANS_DISTRIBUTED_OPERATION_FAILED;
476 }
477 if (!database_->GetLocalDeviceInfo(deviceInfo)) {
478 return ERR_ANS_DISTRIBUTED_OPERATION_FAILED;
479 }
480
481 return ERR_OK;
482 }
483
OnDistributedKvStoreDeathRecipient()484 ErrCode DistributedNotificationManager::OnDistributedKvStoreDeathRecipient()
485 {
486 ANS_LOGD("start");
487 database_ = std::make_shared<DistributedDatabase>(databaseCb_, deviceCb_);
488 if (!database_->RecreateDistributedDB()) {
489 ANS_LOGE("RecreateDistributedDB failed.");
490 return ERR_ANS_DISTRIBUTED_OPERATION_FAILED;
491 }
492 return ERR_OK;
493 }
494 } // namespace Notification
495 } // namespace OHOS
496