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