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