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_watchdog.h"
23 #include "hitrace_meter_adapter.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 if (distributedQueue_ != nullptr) {
67 ffrt::task_handle handler = distributedQueue_->submit_h(std::bind([&]() { callback_ = {}; }));
68 distributedQueue_->wait(handler);
69 }
70 }
71
ResetFfrtQueue()72 void DistributedNotificationManager::ResetFfrtQueue()
73 {
74 if (distributedQueue_ != nullptr) {
75 distributedQueue_.reset();
76 }
77 }
78
GenerateDistributedKey(const std::string & deviceId,const std::string & bundleName,const std::string & label,int32_t id,std::string & key)79 void DistributedNotificationManager::GenerateDistributedKey(
80 const std::string &deviceId, const std::string &bundleName, const std::string &label, int32_t id, std::string &key)
81 {
82 key = deviceId + DELIMITER + bundleName + DELIMITER + label + DELIMITER + ToString(id);
83 }
84
GenerateLocalDistributedKey(const std::string & bundleName,const std::string & label,int32_t id,std::string & key)85 bool DistributedNotificationManager::GenerateLocalDistributedKey(
86 const std::string &bundleName, const std::string &label, int32_t id, std::string &key)
87 {
88 std::string deviceId;
89 if (database_ == nullptr) {
90 ANS_LOGE("database_ is invalid.");
91 return false;
92 }
93 if (!database_->GetLocalDeviceId(deviceId)) {
94 return false;
95 }
96
97 GenerateDistributedKey(deviceId, bundleName, label, id, key);
98 return true;
99 }
100
ResolveDistributedKey(const std::string & key,ResolveKey & resolveKey)101 bool DistributedNotificationManager::ResolveDistributedKey(const std::string &key, ResolveKey &resolveKey)
102 {
103 std::size_t deviceIdPosition = 0;
104 std::size_t deviceIdEndPosition = key.find(DELIMITER, deviceIdPosition);
105 if (deviceIdEndPosition == std::string::npos) {
106 return false;
107 }
108 std::size_t bundleNamePosition = deviceIdEndPosition + DELIMITER.size();
109 std::size_t bundleNameEndPosition = key.find(DELIMITER, bundleNamePosition);
110 if (bundleNameEndPosition == std::string::npos) {
111 return false;
112 }
113 std::size_t labelPosition = bundleNameEndPosition + DELIMITER.size();
114 std::size_t labelEndPosition = key.find_last_of(DELIMITER) - DELIMITER.size() + 1;
115 if (labelEndPosition < labelPosition) {
116 return false;
117 }
118 std::size_t idPosition = key.find_last_of(DELIMITER) + DELIMITER.size();
119
120 resolveKey.deviceId = key.substr(deviceIdPosition, deviceIdEndPosition - deviceIdPosition);
121 resolveKey.bundleName = key.substr(bundleNamePosition, bundleNameEndPosition - bundleNamePosition);
122 resolveKey.label = key.substr(labelPosition, labelEndPosition - labelPosition);
123 resolveKey.id = atoi(&key[idPosition]);
124
125 return true;
126 }
127
CheckDeviceId(const std::string & deviceId,const std::string & key)128 bool DistributedNotificationManager::CheckDeviceId(const std::string &deviceId, const std::string &key)
129 {
130 ResolveKey resolveKey;
131 if (!ResolveDistributedKey(key, resolveKey)) {
132 ANS_LOGE("key <%{public}s> is invalid.", key.c_str());
133 return false;
134 }
135
136 return deviceId == resolveKey.deviceId;
137 }
138
OnDatabaseInsert(const std::string & deviceId,const std::string & key,const std::string & value)139 void DistributedNotificationManager::OnDatabaseInsert(
140 const std::string &deviceId, const std::string &key, const std::string &value)
141 {
142 ANS_LOGD("start");
143 if (distributedQueue_ == nullptr) {
144 ANS_LOGE("Serial queue is nullptr.");
145 return;
146 }
147 distributedQueue_->submit(std::bind([=]() {
148 if (!CheckDeviceId(deviceId, key)) {
149 ANS_LOGD("device id is distinct. deviceId:%{public}s key:%{public}s", deviceId.c_str(), key.c_str());
150 }
151
152 ResolveKey resolveKey;
153 if (!ResolveDistributedKey(key, resolveKey)) {
154 ANS_LOGE("key <%{public}s> is invalidity.", key.c_str());
155 return;
156 }
157
158 sptr<NotificationRequest> request =
159 NotificationJsonConverter::ConvertFromJsonString<NotificationRequest>(value);
160 if (request == nullptr) {
161 ANS_LOGE("convert json to request failed. key:%{public}s", key.c_str());
162 return;
163 }
164
165 PublishCallback(resolveKey.deviceId, resolveKey.bundleName, request);
166 }));
167 }
168
OnDatabaseUpdate(const std::string & deviceId,const std::string & key,const std::string & value)169 void DistributedNotificationManager::OnDatabaseUpdate(
170 const std::string &deviceId, const std::string &key, const std::string &value)
171 {
172 ANS_LOGD("start");
173 if (distributedQueue_ == nullptr) {
174 ANS_LOGE("Serial queue is invalid.");
175 return;
176 }
177 ffrt::task_handle handler = distributedQueue_->submit_h(std::bind([=]() {
178 if (!CheckDeviceId(deviceId, key)) {
179 ANS_LOGD("device id are not the same. deviceId:%{public}s key:%{public}s", 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", deviceId.c_str(), key.c_str());
210 }
211
212 ResolveKey resolveKey;
213 if (!ResolveDistributedKey(key, resolveKey)) {
214 ANS_LOGE("key <%{public}s> is invalid.", key.c_str());
215 return;
216 }
217
218 DeleteCallback(resolveKey.deviceId, resolveKey.bundleName, resolveKey.label, resolveKey.id);
219 }));
220 }
221
OnDeviceConnected(const std::string & deviceId)222 void DistributedNotificationManager::OnDeviceConnected(const std::string &deviceId)
223 {
224 ANS_LOGD("start");
225 if (distributedQueue_ == nullptr) {
226 ANS_LOGE("Serial queue is invalid.");
227 return;
228 }
229 distributedQueue_->submit(std::bind([=]() {
230 if (database_ == nullptr) {
231 ANS_LOGE("OnDeviceConnected failed: database is null");
232 return;
233 }
234 if (!database_->OnDeviceConnected()) {
235 ANS_LOGE("OnDeviceConnected failed.");
236 }
237 }));
238 }
239
OnDeviceDisconnected(const std::string & deviceId)240 void DistributedNotificationManager::OnDeviceDisconnected(const std::string &deviceId)
241 {
242 ANS_LOGD("start");
243 if (distributedQueue_ == nullptr) {
244 ANS_LOGE("Serial queue is invalid.");
245 return;
246 }
247 distributedQueue_->submit(std::bind([=]() {
248 std::string prefixKey = deviceId + DELIMITER;
249 std::vector<DistributedDatabase::Entry> entries;
250 if (database_ == nullptr) {
251 ANS_LOGE("database_ is invalid.");
252 return;
253 }
254 if (!database_->GetEntriesFromDistributedDB(prefixKey, entries)) {
255 ANS_LOGE("GetEntriesFromDistributedDB failed.");
256 return;
257 }
258
259 for (auto index : entries) {
260 ResolveKey resolveKey;
261 if (!ResolveDistributedKey(index.key.ToString(), resolveKey)) {
262 ANS_LOGE("key <%{public}s> is invalid.", index.key.ToString().c_str());
263 continue;
264 }
265
266 DeleteCallback(resolveKey.deviceId, resolveKey.bundleName, resolveKey.label, resolveKey.id);
267 }
268
269 database_->ClearDataByDevice(deviceId);
270
271 std::vector<DistributedDatabase::DeviceInfo> deviceList;
272 if (database_->GetDeviceInfoList(deviceList) == ERR_OK && deviceList.empty()) {
273 database_->RecreateDistributedDB();
274 }
275 }));
276 }
277
PublishCallback(const std::string & deviceId,const std::string & bundleName,sptr<NotificationRequest> & request)278 bool DistributedNotificationManager::PublishCallback(
279 const std::string &deviceId, const std::string &bundleName, sptr<NotificationRequest> &request)
280 {
281 ANS_LOGI("start");
282 if (callback_.OnPublish) {
283 callback_.OnPublish(deviceId, bundleName, request);
284 }
285 ANS_LOGD("end");
286
287 return true;
288 }
289
UpdateCallback(const std::string & deviceId,const std::string & bundleName,sptr<NotificationRequest> & request)290 bool DistributedNotificationManager::UpdateCallback(
291 const std::string &deviceId, const std::string &bundleName, sptr<NotificationRequest> &request)
292 {
293 ANS_LOGI("start");
294 if (callback_.OnUpdate) {
295 callback_.OnUpdate(deviceId, bundleName, request);
296 }
297 ANS_LOGD("end");
298
299 return true;
300 }
301
DeleteCallback(const std::string & deviceId,const std::string & bundleName,const std::string & label,int32_t id)302 bool DistributedNotificationManager::DeleteCallback(
303 const std::string &deviceId, const std::string &bundleName, const std::string &label, int32_t id)
304 {
305 ANS_LOGI("start");
306 if (callback_.OnDelete) {
307 callback_.OnDelete(deviceId, bundleName, label, id);
308 }
309 ANS_LOGD("end");
310
311 return true;
312 }
313
Publish(const std::string & bundleName,const std::string & label,int32_t id,const sptr<NotificationRequest> & request)314 ErrCode DistributedNotificationManager::Publish(
315 const std::string &bundleName, const std::string &label, int32_t id, const sptr<NotificationRequest> &request)
316 {
317 HITRACE_METER_NAME(HITRACE_TAG_NOTIFICATION, __PRETTY_FUNCTION__);
318 ANS_LOGD("start");
319 std::string key;
320 if (!GenerateLocalDistributedKey(bundleName, label, id, key)) {
321 ANS_LOGE("Failed to generate distributed key.");
322 return ERR_ANS_DISTRIBUTED_GET_INFO_FAILED;
323 }
324
325 std::string value;
326 if (!NotificationJsonConverter::ConvertToJsonString(request, value)) {
327 ANS_LOGE("convert request to json failed. key:%{public}s", key.c_str());
328 return ERR_ANS_DISTRIBUTED_OPERATION_FAILED;
329 }
330
331 if (database_ == nullptr) {
332 ANS_LOGE("database_ is nullptr.");
333 return ERR_ANS_DISTRIBUTED_OPERATION_FAILED;
334 }
335 if (!database_->PutToDistributedDB(key, value)) {
336 ANS_LOGE("put to distributed DB failed. key:%{public}s", key.c_str());
337 return ERR_ANS_DISTRIBUTED_OPERATION_FAILED;
338 }
339
340 return ERR_OK;
341 }
342
Update(const std::string & bundleName,const std::string & label,int32_t id,const sptr<NotificationRequest> & request)343 ErrCode DistributedNotificationManager::Update(
344 const std::string &bundleName, const std::string &label, int32_t id, const sptr<NotificationRequest> &request)
345 {
346 ANS_LOGD("start");
347 std::string key;
348 if (!GenerateLocalDistributedKey(bundleName, label, id, key)) {
349 ANS_LOGE("Generate distributed key failed.");
350 return ERR_ANS_DISTRIBUTED_GET_INFO_FAILED;
351 }
352
353 std::string value;
354 if (!NotificationJsonConverter::ConvertToJsonString(request, value)) {
355 ANS_LOGE("convert request to json failed. key:%{public}s", key.c_str());
356 return ERR_ANS_DISTRIBUTED_OPERATION_FAILED;
357 }
358
359 if (database_ == nullptr) {
360 ANS_LOGE("database_ is invalid.");
361 return ERR_ANS_DISTRIBUTED_OPERATION_FAILED;
362 }
363 if (!database_->PutToDistributedDB(key, value)) {
364 ANS_LOGE("put to distributed DB failed. key:%{public}s", key.c_str());
365 return ERR_ANS_DISTRIBUTED_OPERATION_FAILED;
366 }
367 return ERR_OK;
368 }
369
Delete(const std::string & bundleName,const std::string & label,int32_t id)370 ErrCode DistributedNotificationManager::Delete(const std::string &bundleName, const std::string &label, int32_t id)
371 {
372 HITRACE_METER_NAME(HITRACE_TAG_NOTIFICATION, __PRETTY_FUNCTION__);
373 ANS_LOGD("start");
374 std::string key;
375 if (!GenerateLocalDistributedKey(bundleName, label, id, key)) {
376 ANS_LOGE("Generate distributed key failed.");
377 return ERR_ANS_DISTRIBUTED_GET_INFO_FAILED;
378 }
379
380 if (database_ == nullptr) {
381 ANS_LOGE("database_ is nullptr.");
382 return ERR_ANS_DISTRIBUTED_OPERATION_FAILED;
383 }
384 if (!database_->DeleteToDistributedDB(key)) {
385 ANS_LOGE("Failed to DeleteToDistributedDB. key:%{public}s", key.c_str());
386 return ERR_ANS_DISTRIBUTED_OPERATION_FAILED;
387 }
388 return ERR_OK;
389 }
390
DeleteRemoteNotification(const std::string & deviceId,const std::string & bundleName,const std::string & label,int32_t id)391 ErrCode DistributedNotificationManager::DeleteRemoteNotification(
392 const std::string &deviceId, const std::string &bundleName, const std::string &label, int32_t id)
393 {
394 HITRACE_METER_NAME(HITRACE_TAG_NOTIFICATION, __PRETTY_FUNCTION__);
395 ANS_LOGD("start");
396
397 std::string key;
398 GenerateDistributedKey(deviceId, bundleName, label, id, key);
399
400 if (database_ == nullptr) {
401 ANS_LOGE("database_ is invalid.");
402 return ERR_ANS_DISTRIBUTED_OPERATION_FAILED;
403 }
404 if (!database_->DeleteToDistributedDB(key)) {
405 ANS_LOGE("delete to distributed DB failed. key:%{public}s", key.c_str());
406 return ERR_ANS_DISTRIBUTED_OPERATION_FAILED;
407 }
408 return ERR_OK;
409 }
410
RegisterCallback(const IDistributedCallback & callback)411 ErrCode DistributedNotificationManager::RegisterCallback(const IDistributedCallback &callback)
412 {
413 ANS_LOGD("start");
414 if (distributedQueue_ == nullptr) {
415 ANS_LOGE("Serial queue is invalid.");
416 return ERR_ANS_INVALID_PARAM;
417 }
418 ffrt::task_handle handler = distributedQueue_->submit_h(std::bind([&]() { callback_ = callback; }));
419 distributedQueue_->wait(handler);
420 return ERR_OK;
421 }
422
UngegisterCallback()423 ErrCode DistributedNotificationManager::UngegisterCallback()
424 {
425 ANS_LOGD("start");
426 if (distributedQueue_ == nullptr) {
427 ANS_LOGE("Serial queue is invalid.");
428 return ERR_ANS_INVALID_PARAM;
429 }
430 ffrt::task_handle handler = distributedQueue_->submit_h(std::bind([&]() { callback_ = {}; }));
431 distributedQueue_->wait(handler);
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