• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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