• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 * Copyright (c) 2021-2024 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 "notification_analytics_util.h"
17 
18 #include "want_params_wrapper.h"
19 #include "string_wrapper.h"
20 #include "common_event_manager.h"
21 #include "common_event_support.h"
22 #include "common_event_publish_info.h"
23 #include "ans_convert_enum.h"
24 #include "ans_permission_def.h"
25 #include "in_process_call_wrapper.h"
26 #include "report_timer_info.h"
27 #include "time_service_client.h"
28 #include "nlohmann/json.hpp"
29 #include "bundle_manager_helper.h"
30 #include "notification_config_parse.h"
31 #include "notification_preferences.h"
32 #include "os_account_manager_helper.h"
33 #include "notification_constant.h"
34 #include "advanced_notification_inline.h"
35 #include "hitrace_util.h"
36 #include "ffrt.h"
37 
38 namespace OHOS {
39 namespace Notification {
40 constexpr char MESSAGE_DELIMITER = '#';
41 constexpr const int32_t SYNC_WATCH_HEADSET = 2;
42 constexpr const int32_t PUBLISH_ERROR_EVENT_CODE = 0;
43 constexpr const int32_t DELETE_ERROR_EVENT_CODE = 5;
44 constexpr const int32_t MODIFY_ERROR_EVENT_CODE = 6;
45 constexpr const int32_t ANS_CUSTOMIZE_CODE = 7;
46 constexpr const int32_t BADGE_CHANGE_CODE = 201;
47 
48 constexpr const int32_t DEFAULT_ERROR_EVENT_COUNT = 5;
49 constexpr const int32_t DEFAULT_ERROR_EVENT_TIME = 60;
50 constexpr const int32_t MODIFY_ERROR_EVENT_COUNT = 6;
51 constexpr const int32_t MODIFY_ERROR_EVENT_TIME = 60;
52 constexpr const int32_t MAX_NUMBER_EVERY_REPORT = 20;
53 constexpr const int32_t MAX_REPORT_COUNT = 3;
54 constexpr const int32_t MAX_BADGE_AGGRATE_NUM = 20;
55 constexpr const int32_t MAX_NUMBER_EVERY_BADGE_DATA = 20;
56 
57 constexpr const int32_t REPORT_CACHE_MAX_SIZE = 50;
58 constexpr const int32_t SUCCESS_REPORT_CACHE_MAX_SIZE = 60;
59 constexpr const int32_t REPORT_CACHE_INTERVAL_TIME = 30;
60 constexpr const int32_t SUCCESS_REPORT_CACHE_INTERVAL_TIME = 1800;
61 constexpr const int32_t REASON_MAX_LENGTH = 255;
62 constexpr const int32_t MAX_BADGE_NUMBER = 99;
63 constexpr const int32_t SUB_CODE = 100;
64 constexpr const int32_t MAX_TIME = 43200000;
65 constexpr const int32_t MAX_BADGE_CHANGE_REPORT_TIME = 1800000;
66 constexpr const int32_t TIMEOUT_TIME_OF_BADGE = 5400000;
67 constexpr const int32_t NOTIFICATION_MAX_DATA = 100;
68 constexpr const int32_t SOUND_FLAG = 1 << 10;
69 constexpr const int32_t LOCKSCREEN_FLAG = 1 << 11;
70 constexpr const int32_t BANNER_FLAG = 1 << 12;
71 constexpr const int32_t VIBRATION_FLAG = 1 << 13;
72 
73 const static std::string NOTIFICATION_EVENT_PUSH_AGENT = "notification.event.PUSH_AGENT";
74 static ffrt::mutex reportFlowControlMutex_;
75 static std::map<int32_t, std::list<std::chrono::system_clock::time_point>> flowControlTimestampMap_ = {
76     {MODIFY_ERROR_EVENT_CODE, {}},
77     {PUBLISH_ERROR_EVENT_CODE, {}},
78     {DELETE_ERROR_EVENT_CODE, {}},
79     {ANS_CUSTOMIZE_CODE, {}},
80 };
81 static std::map<std::string, BadgeInfo> badgeInfos;
82 static std::map<std::string, ReportLiveViewMessage> liveViewMessages;
83 
84 static ffrt::mutex reportCacheMutex_;
85 static uint64_t reportTimerId = 0;
86 static std::list<ReportCache> reportCacheList;
87 static bool g_reportFlag = false;
88 static std::shared_ptr<ReportTimerInfo> reportTimeInfo = std::make_shared<ReportTimerInfo>();
89 
90 static ffrt::mutex badgeInfosMutex_;
91 static ffrt::mutex reportSuccessCacheMutex_;
92 static uint64_t reportAggregateTimeId = 0;
93 static std::list<ReportCache> successReportCacheList;
94 static bool g_successReportFlag = false;
95 static std::shared_ptr<ReportTimerInfo> reportAggregateTimeInfo = std::make_shared<ReportTimerInfo>();
96 static std::list<ReportCache> reportAggList;
97 
98 static int32_t SLOT_REPORT_INTERVAL = 7 * 24 * NotificationConstant::HOUR_TO_MS;
99 static int64_t lastReportTime_ = 0;
100 static ffrt::mutex lastReportTimeMutex_;
101 static int32_t SLOT_SUB_CODE = 101;
102 static int32_t SLOT_ONCE_REPORT = 10;
103 static uint32_t SLOT_MAX_REPORT = 200;
104 static uint64_t reportSlotEnabledTimerId_ = 0;
105 static std::shared_ptr<ReportTimerInfo> slotTimeInfo = std::make_shared<ReportTimerInfo>();
106 static std::list<ReportSlotMessage> slotEnabledList_;
107 static ffrt::mutex slotEnabledListMutex_;
108 static bool g_reportSlotFlag = false;
109 static ffrt::mutex reportSlotEnabledMutex_;
110 
111 static int32_t LIVEVIEW_SUB_CODE = 202;
112 static int32_t LIVEVIEW_AGGREGATE_NUM = 10;
113 static ffrt::mutex ReportLiveViewMessageMutex_;
114 static uint64_t reportLiveViewMessageTimerId_ = 0;
115 static std::shared_ptr<ReportTimerInfo> liveViewTimeInfo = std::make_shared<ReportTimerInfo>();
116 static int32_t LIVEVIEW_REPORT_INTERVAL = 2 * NotificationConstant::HOUR_TO_MS;
117 static const int32_t LIVE_VIEW_CREATE = 0;
118 static bool g_reportLiveViewFlag = false;
119 OperationalData HaOperationMessage::notificationData = OperationalData();
120 OperationalData HaOperationMessage::liveViewData = OperationalData();
121 
HaMetaMessage(uint32_t sceneId,uint32_t branchId)122 HaMetaMessage::HaMetaMessage(uint32_t sceneId, uint32_t branchId)
123     : sceneId_(sceneId), branchId_(branchId)
124 {
125 }
126 
NeedReport() const127 bool HaMetaMessage::NeedReport() const
128 {
129     if (errorCode_ == ERR_OK && checkfailed_) {
130         return false;
131     }
132     return true;
133 }
134 
SceneId(uint32_t sceneId)135 HaMetaMessage& HaMetaMessage::SceneId(uint32_t sceneId)
136 {
137     sceneId_ = sceneId;
138     return *this;
139 }
140 
BranchId(uint32_t branchId)141 HaMetaMessage& HaMetaMessage::BranchId(uint32_t branchId)
142 {
143     branchId_ = branchId;
144     return *this;
145 }
146 
ErrorCode(uint32_t errorCode)147 HaMetaMessage& HaMetaMessage::ErrorCode(uint32_t errorCode)
148 {
149     errorCode_ = errorCode;
150     return *this;
151 }
152 
Message(const std::string & message,bool print)153 HaMetaMessage& HaMetaMessage::Message(const std::string& message, bool print)
154 {
155     message_ = message;
156     if (print) {
157         ANSR_LOGE("%{public}s, %{public}d", message.c_str(), errorCode_);
158     }
159     return *this;
160 }
161 
Path(const std::string & path)162 HaMetaMessage& HaMetaMessage::Path(const std::string &path)
163 {
164     path_ = path;
165     return *this;
166 }
167 
Append(const std::string & message)168 HaMetaMessage& HaMetaMessage::Append(const std::string& message)
169 {
170     message_+=message;
171     return *this;
172 }
Checkfailed(bool checkfailed)173 HaMetaMessage& HaMetaMessage::Checkfailed(bool checkfailed)
174 {
175     checkfailed_ = checkfailed;
176     return *this;
177 }
178 
BundleName(const std::string & bundleName)179 HaMetaMessage& HaMetaMessage::BundleName(const std::string& bundleName)
180 {
181     bundleName_ = bundleName;
182     return *this;
183 }
184 
AgentBundleName(const std::string & agentBundleName)185 HaMetaMessage& HaMetaMessage::AgentBundleName(const std::string& agentBundleName)
186 {
187     agentBundleName_ = agentBundleName;
188     return *this;
189 }
190 
TypeCode(int32_t typeCode)191 HaMetaMessage& HaMetaMessage::TypeCode(int32_t typeCode)
192 {
193     typeCode_ = typeCode;
194     return *this;
195 }
196 
NotificationId(int32_t notificationId)197 HaMetaMessage& HaMetaMessage::NotificationId(int32_t notificationId)
198 {
199     notificationId_ = notificationId;
200     return *this;
201 }
202 
GetMessage() const203 std::string HaMetaMessage::GetMessage() const
204 {
205     return message_;
206 }
207 
SlotType(int32_t slotType)208 HaMetaMessage& HaMetaMessage::SlotType(int32_t slotType)
209 {
210     slotType_ = static_cast<uint32_t>(slotType);
211     return *this;
212 }
213 
DeleteReason(int32_t deleteReason)214 HaMetaMessage& HaMetaMessage::DeleteReason(int32_t deleteReason)
215 {
216     deleteReason_ = deleteReason;
217     return *this;
218 }
219 
Build() const220 std::string HaMetaMessage::Build() const
221 {
222     return std::to_string(sceneId_) + MESSAGE_DELIMITER +
223         std::to_string(branchId_) + MESSAGE_DELIMITER + std::to_string(errorCode_) +
224         MESSAGE_DELIMITER + message_ + MESSAGE_DELIMITER;
225 }
226 
ToJson(nlohmann::json & jsonObject)227 void OperationalMeta::ToJson(nlohmann::json& jsonObject)
228 {
229     jsonObject["s"] = syncTime;
230     jsonObject["d"] = delTime;
231     jsonObject["c"] = clickTime;
232     jsonObject["r"] = replyTime;
233 }
234 
OperationalData()235 OperationalData::OperationalData()
236 {
237     for (std::string deviceType : NotificationConstant::DEVICESTYPES) {
238         dataMap.insert({deviceType, OperationalMeta()});
239     }
240     time = NotificationAnalyticsUtil::GetCurrentTime();
241 }
242 
ToJson(nlohmann::json & jsonObject)243 void OperationalData::ToJson(nlohmann::json& jsonObject)
244 {
245     for (auto& deviceData : dataMap) {
246         nlohmann::json dataJson;
247         deviceData.second.ToJson(dataJson);
248         jsonObject[deviceData.first] = dataJson;
249     }
250 
251     jsonObject["key"] = keyNode;
252     jsonObject["both"] = syncWatchHead;
253 }
254 
KeyNode(bool keyNodeFlag)255 HaOperationMessage& HaOperationMessage::KeyNode(bool keyNodeFlag)
256 {
257     if (keyNodeFlag) {
258         liveViewData.keyNode++;
259     }
260     return *this;
261 }
262 
ToJson()263 std::string HaOperationMessage::ToJson()
264 {
265     nlohmann::json jsonMessage;
266     nlohmann::json jsonObject;
267     if (isLiveView_) {
268         liveViewData.ToJson(jsonMessage);
269         jsonObject["liveview"] = jsonMessage;
270     } else {
271         notificationData.ToJson(jsonMessage);
272         jsonObject["notification"] =  jsonMessage;
273     }
274     return jsonObject.dump();
275 }
276 
SetPublishTime(const std::vector<std::string> & deviceTypes,OperationalData & data)277 void SetPublishTime(const std::vector<std::string>& deviceTypes, OperationalData& data)
278 {
279     int32_t isWatchHeadSet = 0;
280     for (auto& device : deviceTypes) {
281         if (data.dataMap.find(device) != data.dataMap.end()) {
282             data.dataMap[device].syncTime++;
283             if (device == NotificationConstant::HEADSET_DEVICE_TYPE ||
284                 device == NotificationConstant::WEARABLE_DEVICE_TYPE ||
285                 device == NotificationConstant::LITEWEARABLE_DEVICE_TYPE) {
286                 isWatchHeadSet++;
287             }
288             data.countTime++;
289         }
290     }
291     if (isWatchHeadSet >= SYNC_WATCH_HEADSET) {
292         data.syncWatchHead++;
293     }
294 }
295 
SyncPublish(std::vector<std::string> & deviceTypes)296 HaOperationMessage& HaOperationMessage::SyncPublish(std::vector<std::string>& deviceTypes)
297 {
298     if (isLiveView_) {
299         SetPublishTime(deviceTypes, liveViewData);
300     } else {
301         SetPublishTime(deviceTypes, notificationData);
302     }
303     return *this;
304 }
305 
SyncDelete(std::string deviceType,const std::string & reason)306 HaOperationMessage& HaOperationMessage::SyncDelete(std::string deviceType, const std::string& reason)
307 {
308     if (isLiveView_) {
309         if (liveViewData.dataMap.find(deviceType) != liveViewData.dataMap.end()) {
310             liveViewData.dataMap[deviceType].delTime++;
311             liveViewData.countTime++;
312         }
313     } else {
314         if (notificationData.dataMap.find(deviceType) != notificationData.dataMap.end()) {
315             notificationData.dataMap[deviceType].delTime++;
316             notificationData.countTime++;
317         }
318     }
319     return *this;
320 }
321 
SyncClick(std::string deviceType)322 HaOperationMessage& HaOperationMessage::SyncClick(std::string deviceType)
323 {
324     if (isLiveView_) {
325         if (liveViewData.dataMap.find(deviceType) != liveViewData.dataMap.end()) {
326             liveViewData.dataMap[deviceType].clickTime++;
327             liveViewData.countTime++;
328         }
329     } else {
330         if (notificationData.dataMap.find(deviceType) != notificationData.dataMap.end()) {
331             notificationData.dataMap[deviceType].clickTime++;
332             notificationData.countTime++;
333         }
334     }
335     return *this;
336 }
337 
SyncReply(std::string deviceType)338 HaOperationMessage& HaOperationMessage::SyncReply(std::string deviceType)
339 {
340     if (isLiveView_) {
341         if (liveViewData.dataMap.find(deviceType) != liveViewData.dataMap.end()) {
342             liveViewData.dataMap[deviceType].replyTime++;
343             liveViewData.countTime++;
344         }
345     } else {
346         if (notificationData.dataMap.find(deviceType) != notificationData.dataMap.end()) {
347             notificationData.dataMap[deviceType].replyTime++;
348             notificationData.countTime++;
349         }
350     }
351     return *this;
352 }
353 
DetermineWhetherToSend()354 bool HaOperationMessage::DetermineWhetherToSend()
355 {
356     if (isLiveView_ && liveViewData.keyNode != 0) {
357         return true;
358     }
359     if (isLiveView_) {
360         if (liveViewData.countTime >= NOTIFICATION_MAX_DATA ||
361             (NotificationAnalyticsUtil::GetCurrentTime() - liveViewData.time) >= MAX_TIME) {
362             return true;
363         }
364     } else {
365         if (notificationData.countTime >= NOTIFICATION_MAX_DATA ||
366             (NotificationAnalyticsUtil::GetCurrentTime() - notificationData.time) >= MAX_TIME) {
367             return true;
368         }
369     }
370     return false;
371 }
372 
ResetOperationalData(OperationalData & data)373 void ResetOperationalData(OperationalData& data)
374 {
375     data.countTime = 0;
376     data.keyNode = 0;
377     data.syncWatchHead = 0;
378     data.time = NotificationAnalyticsUtil::GetCurrentTime();
379     for (auto& item : data.dataMap) {
380         item.second = { 0 };
381     }
382 }
383 
ResetData()384 void HaOperationMessage::ResetData()
385 {
386     if (isLiveView_) {
387         ResetOperationalData(liveViewData);
388     } else {
389         ResetOperationalData(notificationData);
390     }
391 }
392 
MakeRequestBundle(const sptr<NotificationRequest> & request)393 void NotificationAnalyticsUtil::MakeRequestBundle(const sptr<NotificationRequest>& request)
394 {
395     if (request->GetOwnerBundleName().empty() && request->GetCreatorBundleName().empty()) {
396         request->SetCreatorUid(IPCSkeleton::GetCallingUid());
397         request->SetCreatorBundleName(GetClientBundleName());
398     }
399 }
400 
ReportTipsEvent(const sptr<NotificationRequest> & request,const HaMetaMessage & message)401 void NotificationAnalyticsUtil::ReportTipsEvent(const sptr<NotificationRequest>& request,
402     const HaMetaMessage& message)
403 {
404     if (request == nullptr) {
405         return;
406     }
407     MakeRequestBundle(request);
408     CommonNotificationEvent(request, PUBLISH_ERROR_EVENT_CODE, message);
409 }
410 
ReportPublishFailedEvent(const sptr<NotificationRequest> & request,const HaMetaMessage & message)411 void NotificationAnalyticsUtil::ReportPublishFailedEvent(const sptr<NotificationRequest>& request,
412     const HaMetaMessage& message)
413 {
414     if (request == nullptr) {
415         return;
416     }
417     MakeRequestBundle(request);
418     CommonNotificationEvent(request, PUBLISH_ERROR_EVENT_CODE, message);
419     ReportLiveViewNumber(request, PUBLISH_ERROR_EVENT_CODE);
420 }
421 
ReportDeleteFailedEvent(const sptr<NotificationRequest> & request,HaMetaMessage & message)422 void NotificationAnalyticsUtil::ReportDeleteFailedEvent(const sptr<NotificationRequest>& request,
423     HaMetaMessage& message)
424 {
425     if (request == nullptr || !message.NeedReport()) {
426         ANS_LOGE("request is null %{public}d", message.NeedReport());
427         return;
428     }
429     std::shared_ptr<NotificationBundleOption> agentBundleNameOption = request->GetAgentBundle();
430     if (agentBundleNameOption != nullptr) {
431         std::string agentBundleName = agentBundleNameOption->GetBundleName();
432         if (!agentBundleName.empty()) {
433             message = message.AgentBundleName(agentBundleName);
434         }
435     }
436     CommonNotificationEvent(request, DELETE_ERROR_EVENT_CODE, message);
437 }
438 
ReportPublishSuccessEvent(const sptr<NotificationRequest> & request,const HaMetaMessage & message)439 void NotificationAnalyticsUtil::ReportPublishSuccessEvent(const sptr<NotificationRequest>& request,
440     const HaMetaMessage& message)
441 {
442     ANS_LOGD("called");
443     if (request == nullptr) {
444         return;
445     }
446     ReportLiveViewNumber(request, ANS_CUSTOMIZE_CODE);
447     if (!IsAllowedBundle(request)) {
448         ANS_LOGW("This Bundle not allowed.");
449         return;
450     }
451 
452     EventFwk::Want want;
453     if (!request->GetOwnerBundleName().empty()) {
454         want.SetBundle(request->GetOwnerBundleName());
455     }
456     if (!request->GetCreatorBundleName().empty()) {
457         want.SetParam("agentBundleName", request->GetCreatorBundleName());
458     }
459     std::string ansData = NotificationAnalyticsUtil::BuildAnsData(request, message);
460     want.SetParam("ansData", ansData);
461 
462     IN_PROCESS_CALL_WITHOUT_RET(AddSuccessListCache(want, ANS_CUSTOMIZE_CODE));
463 }
464 
ReportLiveViewNumber(const sptr<NotificationRequest> & request,const int32_t reportType)465 void NotificationAnalyticsUtil::ReportLiveViewNumber(const sptr<NotificationRequest>& request, const int32_t reportType)
466 {
467     NotificationNapi::ContentType contentType;
468     std::string bundleName = request->GetOwnerBundleName().empty() ? request->GetCreatorBundleName() :
469         request->GetOwnerBundleName();
470     NotificationNapi::AnsEnumUtil::ContentTypeCToJS(
471         static_cast<NotificationContent::Type>(request->GetNotificationType()), contentType);
472     if (contentType == NotificationNapi::ContentType::NOTIFICATION_CONTENT_LIVE_VIEW) {
473         auto content = request->GetContent()->GetNotificationContent();
474         auto liveViewContent = std::static_pointer_cast<NotificationLiveViewContent>(content);
475         if (liveViewContent->GetExtraInfo() != nullptr) {
476             std::string bundle = bundleName + MESSAGE_DELIMITER +
477                 liveViewContent->GetExtraInfo()->GetStringParam("event");
478                 std::lock_guard<ffrt::mutex> lock(ReportLiveViewMessageMutex_);
479                 if (reportType == ANS_CUSTOMIZE_CODE) {
480                     AddLiveViewSuccessNum(bundle, static_cast<int32_t>(liveViewContent->GetLiveViewStatus()));
481                 } else if (reportType == PUBLISH_ERROR_EVENT_CODE) {
482                     AddLiveViewFailedNum(bundle, static_cast<int32_t>(liveViewContent->GetLiveViewStatus()));
483                 }
484             CreateLiveViewTimerExecute();
485         }
486     }
487     if (contentType == NotificationNapi::ContentType::NOTIFICATION_CONTENT_LOCAL_LIVE_VIEW) {
488         std::lock_guard<ffrt::mutex> lock(ReportLiveViewMessageMutex_);
489         std::string bundle = bundleName + "#-99";
490         if (reportType == ANS_CUSTOMIZE_CODE) {
491             AddLocalLiveViewSuccessNum(bundle);
492         } else if (reportType == PUBLISH_ERROR_EVENT_CODE) {
493             AddLocalLiveViewFailedNum(bundle);
494         }
495         CreateLiveViewTimerExecute();
496     }
497 }
498 
AddLiveViewSuccessNum(std::string bundle,int32_t status)499 void NotificationAnalyticsUtil::AddLiveViewSuccessNum(std::string bundle, int32_t status)
500 {
501     auto iter = liveViewMessages.find(bundle);
502     switch (status) {
503         case LIVE_VIEW_CREATE:
504             if (iter != liveViewMessages.end()) {
505                 iter->second.successNum ++;
506             } else {
507                 ReportLiveViewMessage liveViewMessage;
508                 liveViewMessage.FailedNum = 0;
509                 liveViewMessage.successNum = 1;
510                 liveViewMessage.startTime = GetCurrentTime();
511                 liveViewMessages[bundle] = liveViewMessage;
512             }
513             break;
514         default:
515             break;
516     }
517 }
518 
AddLiveViewFailedNum(std::string bundle,int32_t status)519 void NotificationAnalyticsUtil::AddLiveViewFailedNum(std::string bundle, int32_t status)
520 {
521     auto iter = liveViewMessages.find(bundle);
522     switch (status) {
523         case LIVE_VIEW_CREATE:
524             if (iter != liveViewMessages.end()) {
525                 iter->second.FailedNum ++;
526             } else {
527                 ReportLiveViewMessage liveViewMessage;
528                 liveViewMessage.FailedNum = 1;
529                 liveViewMessage.successNum = 0;
530                 liveViewMessage.startTime = GetCurrentTime();
531                 liveViewMessages[bundle] = liveViewMessage;
532             }
533             break;
534         default:
535             break;
536     }
537 }
538 
AddLocalLiveViewFailedNum(std::string bundle)539 void NotificationAnalyticsUtil::AddLocalLiveViewFailedNum(std::string bundle)
540 {
541     auto iter = liveViewMessages.find(bundle);
542     if (iter != liveViewMessages.end()) {
543         iter->second.FailedNum ++;
544     } else {
545         ReportLiveViewMessage liveViewMessage;
546         liveViewMessage.FailedNum = 1;
547         liveViewMessage.successNum = 0;
548         liveViewMessage.startTime = GetCurrentTime();
549         liveViewMessages[bundle] = liveViewMessage;
550     }
551 }
552 
AddLocalLiveViewSuccessNum(std::string bundle)553 void NotificationAnalyticsUtil::AddLocalLiveViewSuccessNum(std::string bundle)
554 {
555     auto iter = liveViewMessages.find(bundle);
556     if (iter != liveViewMessages.end()) {
557         iter->second.successNum ++;
558     } else {
559         ReportLiveViewMessage liveViewMessage;
560         liveViewMessage.FailedNum = 0;
561         liveViewMessage.successNum = 1;
562         liveViewMessage.startTime = GetCurrentTime();
563         liveViewMessages[bundle] = liveViewMessage;
564     }
565 }
566 
CreateLiveViewTimerExecute()567 void NotificationAnalyticsUtil::CreateLiveViewTimerExecute()
568 {
569     if (g_reportLiveViewFlag) {
570         ANS_LOGW("now has liveview message is reporting");
571         return;
572     }
573     sptr<MiscServices::TimeServiceClient> timer = MiscServices::TimeServiceClient::GetInstance();
574     if (timer == nullptr) {
575         ANS_LOGE("null timer");
576         g_reportLiveViewFlag = false;
577         return;
578     }
579     if (reportLiveViewMessageTimerId_ == 0) {
580         reportLiveViewMessageTimerId_ = timer->CreateTimer(liveViewTimeInfo);
581     }
582 
583     auto triggerFunc = [] {
584         ExecuteLiveViewReport();
585     };
586 
587     liveViewTimeInfo->SetCallbackInfo(triggerFunc);
588     timer->StartTimer(reportLiveViewMessageTimerId_, NotificationAnalyticsUtil::GetCurrentTime() +
589         LIVEVIEW_REPORT_INTERVAL);
590     g_reportLiveViewFlag = true;
591 }
592 
ExecuteLiveViewReport()593 void NotificationAnalyticsUtil::ExecuteLiveViewReport()
594 {
595     std::lock_guard<ffrt::mutex> lock(ReportLiveViewMessageMutex_);
596     if (liveViewMessages.empty()) {
597         ANS_LOGI("report end");
598         g_reportLiveViewFlag = false;
599         return;
600     }
601     if (reportAggregateTimeId == 0) {
602         sptr<MiscServices::TimeServiceClient> aggregateTimer = MiscServices::TimeServiceClient::GetInstance();
603         if (aggregateTimer == nullptr) {
604             ANS_LOGE("null aggregateTimer");
605             g_reportLiveViewFlag = false;
606             return;
607         }
608         reportAggregateTimeId = aggregateTimer->CreateTimer(reportAggregateTimeInfo);
609     }
610     ReportCache reportCache = AggregateLiveView();
611     reportAggList.emplace_back(reportCache);
612     if (!g_successReportFlag) {
613         ExecuteSuccessCacheList();
614     }
615     sptr<MiscServices::TimeServiceClient> timer = MiscServices::TimeServiceClient::GetInstance();
616     if (timer == nullptr) {
617         ANS_LOGE("null timer");
618         return;
619     }
620     auto triggerFunc = [] {
621         ExecuteLiveViewReport();
622     };
623     liveViewTimeInfo->SetCallbackInfo(triggerFunc);
624     timer->StartTimer(reportLiveViewMessageTimerId_, NotificationAnalyticsUtil::GetCurrentTime() +
625         LIVEVIEW_REPORT_INTERVAL);
626     g_reportLiveViewFlag = true;
627 }
628 
AggregateLiveView()629 ReportCache NotificationAnalyticsUtil::AggregateLiveView()
630 {
631     nlohmann::json ansData;
632     ansData["subCode"] = std::to_string(LIVEVIEW_SUB_CODE);
633     int32_t aggreCount = LIVEVIEW_AGGREGATE_NUM;
634     std::string data;
635     std::vector<std::string> reportBundles;
636     int64_t startTime = GetCurrentTime();
637 
638     std::vector<std::pair<std::string, ReportLiveViewMessage>> messageVector(liveViewMessages.begin(),
639         liveViewMessages.end());
640     std::sort(messageVector.begin(), messageVector.end(), [](const std::pair<std::string, ReportLiveViewMessage> &a,
641         std::pair<std::string, ReportLiveViewMessage> &b) {
642             return a.second.startTime < b.second.startTime;
643     });
644     for (const auto &message : messageVector) {
645         ReportLiveViewMessage liveViewData = message.second;
646         std::string create = std::to_string(liveViewData.successNum) + "," + std::to_string(liveViewData.FailedNum);
647         std::string update;
648         std::string end;
649         std::string cancel;
650         std::string singleData = message.first + ":" + create + MESSAGE_DELIMITER +
651             update + MESSAGE_DELIMITER + end + MESSAGE_DELIMITER + cancel + MESSAGE_DELIMITER;
652         data += singleData;
653         startTime = startTime < liveViewData.startTime ? startTime : liveViewData.startTime;
654         reportBundles.emplace_back(message.first);
655         aggreCount --;
656         if (aggreCount <= 0) {
657             break;
658         }
659         data += ",";
660     }
661     for (auto bundle : reportBundles) {
662         liveViewMessages.erase(bundle);
663     }
664     ansData["data"] = data;
665     ansData["startTime"] = startTime;
666     ansData["endTime"] = GetCurrentTime();
667     std::string message = ansData.dump(-1, ' ', false, nlohmann::json::error_handler_t::replace);
668     EventFwk::Want want;
669     want.SetAction(NOTIFICATION_EVENT_PUSH_AGENT);
670     want.SetParam("ansData", message);
671 
672     ReportCache reportCache;
673     reportCache.want = want;
674     reportCache.eventCode = ANS_CUSTOMIZE_CODE;
675     return reportCache;
676 }
677 
IsAllowedBundle(const sptr<NotificationRequest> & request)678 bool NotificationAnalyticsUtil::IsAllowedBundle(const sptr<NotificationRequest>& request)
679 {
680     ANS_LOGD("called");
681     std::string bundleName = request->GetOwnerBundleName();
682     return DelayedSingleton<NotificationConfigParse>::GetInstance()->IsReportTrustList(bundleName);
683 }
684 
BuildAnsData(const sptr<NotificationRequest> & request,const HaMetaMessage & message)685 std::string NotificationAnalyticsUtil::BuildAnsData(const sptr<NotificationRequest>& request,
686     const HaMetaMessage& message)
687 {
688     ANS_LOGD("called");
689     nlohmann::json ansData;
690     std::shared_ptr<AAFwk::WantParams> extraInfo = nullptr;
691     if (request->GetUnifiedGroupInfo() != nullptr &&
692         request->GetUnifiedGroupInfo()->GetExtraInfo() != nullptr) {
693         extraInfo = request->GetUnifiedGroupInfo()->GetExtraInfo();
694     } else {
695         extraInfo = std::make_shared<AAFwk::WantParams>();
696     }
697     nlohmann::json extraInfoJson;
698     std::string msgId = extraInfo->GetWantParams("pushData").GetStringParam("msgId");
699     if (!msgId.empty()) {
700         extraInfoJson["msgId"] = msgId;
701     }
702     std::string uniqMsgId = extraInfo->GetWantParams("pushData").GetStringParam("mcMsgId");
703     if (!uniqMsgId.empty()) {
704         extraInfoJson["mcMsgId"] = uniqMsgId;
705     }
706 
707     ansData["extraInfo"] = extraInfoJson.dump(-1, ' ', false, nlohmann::json::error_handler_t::replace);
708     ansData["uid"] = std::to_string(request->GetOwnerUid());
709     ansData["id"] = std::to_string(request->GetNotificationId());
710     NotificationNapi::SlotType slotType;
711     NotificationNapi::AnsEnumUtil::SlotTypeCToJS(
712         static_cast<NotificationConstant::SlotType>(request->GetSlotType()), slotType);
713     NotificationNapi::ContentType contentType;
714     NotificationNapi::AnsEnumUtil::ContentTypeCToJS(
715         static_cast<NotificationContent::Type>(request->GetNotificationType()), contentType);
716     ansData["slotType"] = static_cast<int32_t>(slotType);
717     ansData["contentType"] = std::to_string(static_cast<int32_t>(contentType));
718     ansData["reminderFlags"] = std::to_string(static_cast<int32_t>(request->GetFlags()->GetReminderFlags()));
719     uint32_t controlFlags = request->GetNotificationControlFlags();
720     std::shared_ptr<NotificationFlags> tempFlags = request->GetFlags();
721     ansData["ControlFlags"] = SetControlFlags(tempFlags, controlFlags);
722     ansData["class"] = request->GetClassification();
723     ansData["deviceStatus"] = GetDeviceStatus(request);
724     auto now = std::chrono::duration_cast<std::chrono::milliseconds>(
725     std::chrono::system_clock::now().time_since_epoch()).count();
726     ansData["time"] = now;
727     ansData["traceId"] = GetTraceIdStr();
728     ANS_LOGI("Ansdata built, the controlFlags is %{public}d, deviceStatus is %{public}s",
729         controlFlags, GetDeviceStatus(request).c_str());
730     return ansData.dump(-1, ' ', false, nlohmann::json::error_handler_t::replace);
731 }
732 
GetDeviceStatus(const sptr<NotificationRequest> & request)733 std::string NotificationAnalyticsUtil::GetDeviceStatus(const sptr<NotificationRequest>& request)
734 {
735     std::map<std::string, std::string> deviceStatus = request->GetdeviceStatus();
736     nlohmann::json deviceStatusJson;
737     for (std::map<std::string, std::string>::const_iterator iter = deviceStatus.begin();
738         iter != deviceStatus.end(); ++iter) {
739         deviceStatusJson[iter->first] = iter->second;
740     }
741     return deviceStatusJson.dump(-1, ' ', false, nlohmann::json::error_handler_t::replace);
742 }
SetControlFlags(const std::shared_ptr<NotificationFlags> & flags,uint32_t & controlFlags)743 uint32_t NotificationAnalyticsUtil::SetControlFlags(const std::shared_ptr<NotificationFlags> &flags,
744     uint32_t &controlFlags)
745 {
746     if (flags->IsSoundEnabled() == NotificationConstant::FlagStatus::OPEN) {
747         controlFlags |= SOUND_FLAG;
748     } else {
749         controlFlags &= ~SOUND_FLAG;
750     }
751     if (flags->IsVibrationEnabled() == NotificationConstant::FlagStatus::OPEN) {
752         controlFlags |= VIBRATION_FLAG;
753     } else {
754         controlFlags &= ~VIBRATION_FLAG;
755     }
756     if (flags->IsLockScreenVisblenessEnabled()) {
757         controlFlags |= LOCKSCREEN_FLAG;
758     } else {
759         controlFlags &= ~LOCKSCREEN_FLAG;
760     }
761     if (flags->IsBannerEnabled()) {
762         controlFlags |= BANNER_FLAG;
763     } else {
764         controlFlags &= ~BANNER_FLAG;
765     }
766     return controlFlags;
767 }
768 
CommonNotificationEvent(const sptr<NotificationRequest> & request,int32_t eventCode,const HaMetaMessage & message)769 void NotificationAnalyticsUtil::CommonNotificationEvent(const sptr<NotificationRequest>& request,
770     int32_t eventCode, const HaMetaMessage& message)
771 {
772     if (request == nullptr) {
773         return;
774     }
775 
776     if (!ReportFlowControl(eventCode)) {
777         ANS_LOGI("Publish event failed, eventCode:%{public}d, reason:%{public}s",
778             eventCode, message.Build().c_str());
779         return;
780     }
781     EventFwk::Want want;
782     std::string extraInfo;
783     extraInfo = NotificationAnalyticsUtil::BuildExtraInfoWithReq(message, request);
784     NotificationAnalyticsUtil::SetCommonWant(want, message, extraInfo);
785 
786     want.SetParam("typeCode", message.typeCode_);
787     IN_PROCESS_CALL_WITHOUT_RET(ReportNotificationEvent(
788         request, want, eventCode, message.Build()));
789 }
790 
ReportSAPublishSuccessEvent(const sptr<NotificationRequest> & request,int32_t callUid)791 void NotificationAnalyticsUtil::ReportSAPublishSuccessEvent(const sptr<NotificationRequest>& request, int32_t callUid)
792 {
793     ANS_LOGD("called");
794     if (request == nullptr) {
795         return;
796     }
797 
798     EventFwk::Want want;
799     nlohmann::json ansData;
800     ansData["ownerUid"] = std::to_string(request->GetOwnerUid());
801     ansData["createUid"] = std::to_string(request->GetCreatorUid());
802     ansData["callUid"] = std::to_string(callUid);
803     ansData["slotType"] = static_cast<int32_t>(request->GetSlotType());
804     ansData["contentType"] = static_cast<int32_t>(request->GetNotificationType());
805     ansData["isAgent"] = static_cast<int32_t>(request->IsAgentNotification());
806     std::string message = ansData.dump(-1, ' ', false, nlohmann::json::error_handler_t::replace);
807     want.SetParam("ansData", message);
808     want.SetAction(NOTIFICATION_EVENT_PUSH_AGENT);
809 
810     IN_PROCESS_CALL_WITHOUT_RET(AddListCache(want, ANS_CUSTOMIZE_CODE));
811 }
812 
ReportPublishWithUserInput(const sptr<NotificationRequest> & request)813 void NotificationAnalyticsUtil::ReportPublishWithUserInput(const sptr<NotificationRequest>& request)
814 {
815     ANS_LOGD("called");
816     if (request == nullptr || !request->HasUserInputButton()) {
817         return;
818     }
819 
820     EventFwk::Want want;
821     nlohmann::json ansData;
822     if (!request->GetOwnerBundleName().empty()) {
823         ansData["ownerBundleName"] = request->GetOwnerBundleName();
824     }
825     if (!request->GetCreatorBundleName().empty()) {
826         ansData["createBundleName"] = request->GetCreatorBundleName();
827     }
828     ansData["userInput"] = true;
829     ansData["slotType"] = static_cast<int32_t>(request->GetSlotType());
830     ansData["contentType"] = static_cast<int32_t>(request->GetNotificationType());
831     std::string message = ansData.dump(-1, ' ', false, nlohmann::json::error_handler_t::replace);
832     want.SetParam("ansData", message);
833     want.SetAction(NOTIFICATION_EVENT_PUSH_AGENT);
834 
835     IN_PROCESS_CALL_WITHOUT_RET(AddListCache(want, ANS_CUSTOMIZE_CODE));
836 }
837 
ReportNotificationEvent(const sptr<NotificationRequest> & request,EventFwk::Want want,int32_t eventCode,const std::string & reason)838 void NotificationAnalyticsUtil::ReportNotificationEvent(const sptr<NotificationRequest>& request,
839     EventFwk::Want want, int32_t eventCode, const std::string& reason)
840 {
841     NotificationNapi::SlotType slotType;
842     NotificationNapi::AnsEnumUtil::SlotTypeCToJS(
843         static_cast<NotificationConstant::SlotType>(request->GetSlotType()), slotType);
844     NotificationNapi::ContentType contentType;
845     NotificationNapi::AnsEnumUtil::ContentTypeCToJS(
846         static_cast<NotificationContent::Type>(request->GetNotificationType()), contentType);
847 
848     want.SetParam("id", request->GetNotificationId());
849     want.SetParam("uid", request->GetOwnerUid());
850     want.SetParam("slotType", static_cast<int32_t>(slotType));
851     want.SetParam("contentType", std::to_string(static_cast<int32_t>(contentType)));
852 
853     if (!request->GetCreatorBundleName().empty()) {
854         want.SetParam("agentBundleName", request->GetCreatorBundleName());
855     }
856     if (!request->GetOwnerBundleName().empty()) {
857         want.SetBundle(request->GetOwnerBundleName());
858     }
859     IN_PROCESS_CALL_WITHOUT_RET(AddListCache(want, eventCode));
860 }
861 
ReportModifyEvent(const HaMetaMessage & message)862 void NotificationAnalyticsUtil::ReportModifyEvent(const HaMetaMessage& message)
863 {
864     if (!ReportFlowControl(MODIFY_ERROR_EVENT_CODE)) {
865         ANS_LOGI("Publish event failed, reason:%{public}s", message.Build().c_str());
866         return;
867     }
868     EventFwk::Want want;
869     std::string extraInfo = NotificationAnalyticsUtil::BuildExtraInfo(message);
870     NotificationAnalyticsUtil::SetCommonWant(want, message, extraInfo);
871 
872     std::string bundle;
873     int32_t callingUid = IPCSkeleton::GetCallingUid();
874     std::shared_ptr<BundleManagerHelper> bundleManager = BundleManagerHelper::GetInstance();
875     if (bundleManager != nullptr) {
876         bundle = bundleManager->GetBundleNameByUid(callingUid);
877     }
878     want.SetBundle(bundle + "_" + std::to_string(callingUid));
879     want.SetParam("slotType", static_cast<int32_t>(message.slotType_));
880     IN_PROCESS_CALL_WITHOUT_RET(AddListCache(want, MODIFY_ERROR_EVENT_CODE));
881 }
882 
ReportDeleteFailedEvent(const HaMetaMessage & message)883 void NotificationAnalyticsUtil::ReportDeleteFailedEvent(const HaMetaMessage& message)
884 {
885     if (!ReportFlowControl(DELETE_ERROR_EVENT_CODE)) {
886         ANS_LOGE("Publish event failed, reason:%{public}s", message.Build().c_str());
887         return;
888     }
889     EventFwk::Want want;
890     std::string extraInfo = NotificationAnalyticsUtil::BuildExtraInfo(message);
891     NotificationAnalyticsUtil::SetCommonWant(want, message, extraInfo);
892 
893     want.SetParam("agentBundleName", message.agentBundleName_);
894     want.SetParam("typeCode", message.typeCode_);
895     want.SetParam("id", message.notificationId_);
896     want.SetParam("deleteReason", message.deleteReason_);
897 
898     IN_PROCESS_CALL_WITHOUT_RET(AddListCache(want, DELETE_ERROR_EVENT_CODE));
899 }
900 
ReportNotificationEvent(EventFwk::Want want,int32_t eventCode,const std::string & reason)901 void NotificationAnalyticsUtil::ReportNotificationEvent(EventFwk::Want want,
902     int32_t eventCode, const std::string& reason)
903 {
904     EventFwk::CommonEventPublishInfo publishInfo;
905     publishInfo.SetSubscriberPermissions({OHOS_PERMISSION_NOTIFICATION_AGENT_CONTROLLER});
906     EventFwk::CommonEventData commonData {want, eventCode, ""};
907     ANS_LOGD("Publish event success %{public}d, %{public}s", eventCode, reason.c_str());
908     if (!EventFwk::CommonEventManager::PublishCommonEvent(commonData, publishInfo)) {
909         ANS_LOGE("Publish event failed %{public}d, %{public}s", eventCode, reason.c_str());
910     }
911 }
912 
ReportFlowControl(const int32_t reportType)913 bool NotificationAnalyticsUtil::ReportFlowControl(const int32_t reportType)
914 {
915     std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
916     std::lock_guard<ffrt::mutex> lock(reportFlowControlMutex_);
917     auto iter = flowControlTimestampMap_.find(reportType);
918     if (iter == flowControlTimestampMap_.end()) {
919         return false;
920     }
921     auto& list = iter->second;
922     FlowControllerOption option = GetFlowOptionByType(reportType);
923     RemoveExpired(list, now, option.time);
924     int32_t size = static_cast<int32_t>(list.size());
925     int32_t count = option.count;
926     if (size >= count) {
927         return false;
928     }
929     list.push_back(now);
930     return true;
931 }
932 
RemoveExpired(std::list<std::chrono::system_clock::time_point> & list,const std::chrono::system_clock::time_point & now,int32_t time)933 void NotificationAnalyticsUtil::RemoveExpired(std::list<std::chrono::system_clock::time_point> &list,
934     const std::chrono::system_clock::time_point &now, int32_t time)
935 {
936     auto iter = list.begin();
937     while (iter != list.end()) {
938         if (abs(now - *iter) > std::chrono::seconds(time)) {
939             iter = list.erase(iter);
940         } else {
941             break;
942         }
943     }
944 }
945 
GetFlowOptionByType(const int32_t reportType)946 FlowControllerOption NotificationAnalyticsUtil::GetFlowOptionByType(const int32_t reportType)
947 {
948     FlowControllerOption option;
949     switch (reportType) {
950         case MODIFY_ERROR_EVENT_CODE:
951             option.count = MODIFY_ERROR_EVENT_COUNT;
952             option.time = MODIFY_ERROR_EVENT_TIME;
953             break;
954         default:
955             option.count = DEFAULT_ERROR_EVENT_COUNT;
956             option.time = DEFAULT_ERROR_EVENT_TIME;
957             break;
958     }
959     return option;
960 }
961 
BuildExtraInfo(const HaMetaMessage & message)962 std::string NotificationAnalyticsUtil::BuildExtraInfo(const HaMetaMessage& message)
963 {
964     nlohmann::json reason;
965     reason["scene"] = message.sceneId_;
966     reason["branch"] = message.branchId_;
967     reason["innerErr"] = message.errorCode_;
968     reason["detail"] = message.message_;
969 
970     auto now = std::chrono::duration_cast<std::chrono::milliseconds>(
971         std::chrono::system_clock::now().time_since_epoch()).count();
972     reason["time"] = now;
973 
974     std::shared_ptr<AAFwk::WantParams> extraInfo = std::make_shared<AAFwk::WantParams>();
975 
976     reason["detail"] = "";
977     int32_t reasonFixedSize =
978         static_cast<int32_t>(reason.dump(-1, ' ', false, nlohmann::json::error_handler_t::replace).size());
979     int32_t leftSpace = REASON_MAX_LENGTH - reasonFixedSize;
980     if (leftSpace < 0) {
981         std::string basicInfo = std::to_string(message.sceneId_) + MESSAGE_DELIMITER +
982             std::to_string(message.branchId_) + MESSAGE_DELIMITER +
983             std::to_string(message.errorCode_) + MESSAGE_DELIMITER +
984             std::to_string(now) + " Reason fixed size exceeds limit";
985         extraInfo->SetParam("reason", AAFwk::String::Box(basicInfo));
986         ANS_LOGI("%{public}s", basicInfo.c_str());
987     } else {
988         reason["detail"] = message.message_.substr(0, leftSpace);
989         extraInfo->SetParam("reason",
990             AAFwk::String::Box(reason.dump(-1, ' ', false, nlohmann::json::error_handler_t::replace)));
991     }
992 
993     AAFwk::WantParamWrapper wWrapper(*extraInfo);
994 
995     return wWrapper.ToString();
996 }
997 
BuildExtraInfoWithReq(const HaMetaMessage & message,const sptr<NotificationRequest> & request)998 std::string NotificationAnalyticsUtil::BuildExtraInfoWithReq(const HaMetaMessage& message,
999     const sptr<NotificationRequest>& request)
1000 {
1001     NotificationNapi::ContentType contentType;
1002     NotificationNapi::AnsEnumUtil::ContentTypeCToJS(
1003         static_cast<NotificationContent::Type>(request->GetNotificationType()), contentType);
1004     nlohmann::json reason;
1005     if (contentType == NotificationNapi::ContentType::NOTIFICATION_CONTENT_LIVE_VIEW) {
1006         auto content = request->GetContent()->GetNotificationContent();
1007         auto liveViewContent = std::static_pointer_cast<NotificationLiveViewContent>(content);
1008         reason["status"] = static_cast<int32_t>(liveViewContent->GetLiveViewStatus());
1009         if (liveViewContent->GetExtraInfo() != nullptr) {
1010             reason["et"] = liveViewContent->GetExtraInfo()->GetStringParam("event");
1011             reason["lt"] = liveViewContent->GetExtraInfo()->GetIntParam("LayoutData.layoutType", -1);
1012         }
1013     }
1014 
1015     reason["scene"] = message.sceneId_;
1016     reason["branch"] = message.branchId_;
1017     reason["innerErr"] = message.errorCode_;
1018     reason["detail"] = message.message_;
1019 
1020     auto now = std::chrono::duration_cast<std::chrono::milliseconds>(
1021         std::chrono::system_clock::now().time_since_epoch()).count();
1022     reason["time"] = now;
1023 
1024     reason["traceId"] = GetTraceIdStr();
1025     std::shared_ptr<AAFwk::WantParams> extraInfo = nullptr;
1026     if (request->GetUnifiedGroupInfo() != nullptr &&
1027         request->GetUnifiedGroupInfo()->GetExtraInfo() != nullptr) {
1028         const auto originExtraInfo = request->GetUnifiedGroupInfo()->GetExtraInfo();
1029         extraInfo = std::make_shared<AAFwk::WantParams>(*originExtraInfo);
1030     } else {
1031         extraInfo = std::make_shared<AAFwk::WantParams>();
1032     }
1033 
1034     reason["detail"] = "";
1035     int32_t reasonFixedSize =
1036         static_cast<int32_t>(reason.dump(-1, ' ', false, nlohmann::json::error_handler_t::replace).size());
1037     int32_t leftSpace = REASON_MAX_LENGTH - reasonFixedSize;
1038     if (leftSpace < 0) {
1039         std::string basicInfo = std::to_string(message.sceneId_) + MESSAGE_DELIMITER +
1040             std::to_string(message.branchId_) + MESSAGE_DELIMITER +
1041             std::to_string(message.errorCode_) + MESSAGE_DELIMITER +
1042             std::to_string(now) + " Reason fixed size exceeds limit";
1043         extraInfo->SetParam("reason", AAFwk::String::Box(basicInfo));
1044         ANS_LOGI("%{public}s", basicInfo.c_str());
1045     } else {
1046         reason["detail"] = message.message_.substr(0, leftSpace);
1047         extraInfo->SetParam("reason",
1048             AAFwk::String::Box(reason.dump(-1, ' ', false, nlohmann::json::error_handler_t::replace)));
1049     }
1050 
1051     AAFwk::WantParamWrapper wWrapper(*extraInfo);
1052 
1053     return wWrapper.ToString();
1054 }
1055 
GetTraceIdStr()1056 std::string NotificationAnalyticsUtil::GetTraceIdStr()
1057 {
1058     OHOS::HiviewDFX::HiTraceId traceId = OHOS::HiviewDFX::HiTraceChain::GetId();
1059     std::stringstream chainId;
1060     chainId << std::hex << traceId.GetChainId();
1061     std::string hexTransId;
1062     chainId >> std::hex >> hexTransId;
1063     return hexTransId;
1064 }
1065 
SetCommonWant(EventFwk::Want & want,const HaMetaMessage & message,std::string & extraInfo)1066 void NotificationAnalyticsUtil::SetCommonWant(EventFwk::Want& want, const HaMetaMessage& message,
1067     std::string& extraInfo)
1068 {
1069     want.SetBundle(message.bundleName_);
1070     want.SetParam("extraInfo", extraInfo);
1071     want.SetAction(NOTIFICATION_EVENT_PUSH_AGENT);
1072 }
1073 
AddListCache(EventFwk::Want & want,int32_t eventCode)1074 void NotificationAnalyticsUtil::AddListCache(EventFwk::Want& want, int32_t eventCode)
1075 {
1076     std::lock_guard<ffrt::mutex> lock(reportCacheMutex_);
1077     int32_t size = static_cast<int32_t>(reportCacheList.size());
1078     if (size >= REPORT_CACHE_MAX_SIZE) {
1079         ANS_LOGW("list size is max");
1080         return;
1081     }
1082 
1083     if (reportTimerId == 0) {
1084         sptr<MiscServices::TimeServiceClient> timer = MiscServices::TimeServiceClient::GetInstance();
1085         if (timer == nullptr) {
1086             ANS_LOGE("null timer");
1087             return;
1088         }
1089         reportTimerId = timer->CreateTimer(reportTimeInfo);
1090     }
1091 
1092     ReportCache reportCache;
1093     reportCache.want = want;
1094     reportCache.eventCode = eventCode;
1095     reportCacheList.push_back(reportCache);
1096     if (!g_reportFlag) {
1097         ExecuteCacheList();
1098     }
1099 }
1100 
ReportBadgeChange(const sptr<BadgeNumberCallbackData> & badgeData)1101 void NotificationAnalyticsUtil::ReportBadgeChange(const sptr<BadgeNumberCallbackData> &badgeData)
1102 {
1103     ANS_LOGD("called");
1104     if (badgeData == nullptr) {
1105         return;
1106     }
1107 
1108     BadgeInfo badgeInfo;
1109     auto now = std::chrono::duration_cast<std::chrono::milliseconds>(
1110         std::chrono::system_clock::now().time_since_epoch()).count();
1111     std::string bundle = badgeData->GetBundle() + "_"  + std::to_string(badgeData->GetUid());
1112     int32_t badgeNumber = badgeData->GetBadgeNumber();
1113     std::string badgeNumStr = (badgeNumber > MAX_BADGE_NUMBER) ? "99+" : std::to_string(badgeNumber);
1114     {
1115         std::lock_guard<ffrt::mutex> lock(badgeInfosMutex_);
1116         auto iter = badgeInfos.find(bundle);
1117         if (iter != badgeInfos.end()) {
1118             badgeInfo.badgeNum = iter->second.badgeNum + "_" + badgeNumStr;
1119             badgeInfo.time = iter->second.time + "_" + std::to_string(now - iter->second.startTime);
1120             badgeInfo.changeCount = ++ iter->second.changeCount;
1121             badgeInfo.startTime = iter->second.startTime;
1122             badgeInfo.isNeedReport = iter->second.isNeedReport;
1123         } else {
1124             badgeInfo.badgeNum = badgeNumStr;
1125             badgeInfo.startTime = now;
1126             badgeInfo.time = std::to_string(now);
1127             badgeInfo.changeCount = 1;
1128             badgeInfo.isNeedReport = false;
1129         }
1130         AddToBadgeInfos(bundle, badgeInfo);
1131     }
1132 
1133     CheckBadgeReport();
1134 }
1135 
ReportPublishBadge(const sptr<NotificationRequest> & request)1136 void NotificationAnalyticsUtil::ReportPublishBadge(const sptr<NotificationRequest>& request)
1137 {
1138     ANS_LOGD("called");
1139     if (request == nullptr) {
1140         return;
1141     }
1142 
1143     if (request->GetBadgeNumber() <= 0) {
1144         return;
1145     }
1146     BadgeInfo badgeInfo;
1147     auto now = std::chrono::duration_cast<std::chrono::milliseconds>(
1148         std::chrono::system_clock::now().time_since_epoch()).count();
1149     std::string bundle = request->GetOwnerBundleName() + "_"  + std::to_string(request->GetOwnerUid());
1150     uint32_t badgeNumber = request->GetBadgeNumber();
1151     std::string badgeNumStr = (badgeNumber > MAX_BADGE_NUMBER) ? "99+" : std::to_string(badgeNumber);
1152     {
1153         std::lock_guard<ffrt::mutex> lock(badgeInfosMutex_);
1154         auto iter = badgeInfos.find(bundle);
1155         if (iter != badgeInfos.end()) {
1156             badgeInfo.badgeNum = iter->second.badgeNum + "_+" + badgeNumStr;
1157             badgeInfo.time = iter->second.time + "_" + std::to_string(now - iter->second.startTime);
1158             badgeInfo.changeCount = ++ iter->second.changeCount;
1159             badgeInfo.startTime = iter->second.startTime;
1160             badgeInfo.isNeedReport = iter->second.isNeedReport;
1161         } else {
1162             badgeInfo.badgeNum = "+" + badgeNumStr;
1163             badgeInfo.startTime = now;
1164             badgeInfo.time = std::to_string(now);
1165             badgeInfo.changeCount = 1;
1166             badgeInfo.isNeedReport = false;
1167         }
1168         AddToBadgeInfos(bundle, badgeInfo);
1169     }
1170 
1171     CheckBadgeReport();
1172 }
1173 
AddToBadgeInfos(std::string bundle,BadgeInfo & badgeInfo)1174 void NotificationAnalyticsUtil::AddToBadgeInfos(std::string bundle, BadgeInfo& badgeInfo)
1175 {
1176     int32_t count = 0;
1177     auto iter = badgeInfos.find(bundle);
1178     if (iter != badgeInfos.end() && badgeInfo.changeCount == MAX_NUMBER_EVERY_BADGE_DATA) {
1179         for (const auto& pair : badgeInfos) {
1180             if (pair.first.find(bundle) != std::string::npos) {
1181                 count++;
1182             }
1183         }
1184         std::string newBundle = bundle + "_" + std::to_string(count);
1185         badgeInfos[newBundle] = badgeInfo;
1186         badgeInfos.erase(bundle);
1187     } else {
1188         badgeInfos[bundle] = badgeInfo;
1189     }
1190 }
1191 
CheckBadgeReport()1192 void NotificationAnalyticsUtil::CheckBadgeReport()
1193 {
1194     int32_t needReportCount = 0;
1195     bool timeoutReport = false;
1196     auto now = std::chrono::duration_cast<std::chrono::milliseconds>(
1197         std::chrono::system_clock::now().time_since_epoch()).count();
1198     {
1199         std::lock_guard<ffrt::mutex> lock(badgeInfosMutex_);
1200         for (auto& pair : badgeInfos) {
1201             if (pair.second.changeCount == MAX_NUMBER_EVERY_BADGE_DATA ||
1202                 now - pair.second.startTime > MAX_BADGE_CHANGE_REPORT_TIME) {
1203                 pair.second.isNeedReport = true;
1204             }
1205             if (pair.second.isNeedReport == true) {
1206                 needReportCount ++;
1207             }
1208             if (now - pair.second.startTime > TIMEOUT_TIME_OF_BADGE) {
1209                 timeoutReport = true;
1210             }
1211         }
1212     }
1213 
1214     if (timeoutReport || needReportCount >= MAX_BADGE_AGGRATE_NUM) {
1215         AggregateBadgeChange();
1216     }
1217 }
1218 
AggregateBadgeChange()1219 void NotificationAnalyticsUtil::AggregateBadgeChange()
1220 {
1221     EventFwk::Want want;
1222     nlohmann::json ansData;
1223     std::string badgeMessage;
1224     std::vector<std::string> removeBundles;
1225     want.SetAction(NOTIFICATION_EVENT_PUSH_AGENT);
1226     ansData["subCode"] = std::to_string(BADGE_CHANGE_CODE);
1227     {
1228         std::lock_guard<ffrt::mutex> lock(badgeInfosMutex_);
1229         for (const auto& pair : badgeInfos) {
1230             const std::string bundle = pair.first;
1231             const BadgeInfo info = pair.second;
1232             if (!info.isNeedReport) {
1233                 continue;
1234             }
1235             if (!badgeMessage.empty()) {
1236                 badgeMessage += ",";
1237             }
1238             badgeMessage += bundle + ":{" + info.badgeNum + "," + info.time + "}";
1239             removeBundles.emplace_back(bundle);
1240         }
1241         ansData["data"] = badgeMessage;
1242         std::string message = ansData.dump(-1, ' ', false, nlohmann::json::error_handler_t::replace);
1243         want.SetParam("ansData", message);
1244 
1245         if (reportAggregateTimeId == 0) {
1246             sptr<MiscServices::TimeServiceClient> aggregateTimer = MiscServices::TimeServiceClient::GetInstance();
1247             if (aggregateTimer == nullptr) {
1248                 ANS_LOGE("null aggregateTimer");
1249                 return;
1250             }
1251             reportAggregateTimeId = aggregateTimer->CreateTimer(reportAggregateTimeInfo);
1252         }
1253 
1254         ReportCache reportInfo;
1255         reportInfo.want = want;
1256         reportInfo.eventCode = ANS_CUSTOMIZE_CODE ;
1257         reportAggList.emplace_back(reportInfo);
1258 
1259         for (auto bundle : removeBundles) {
1260             badgeInfos.erase(bundle);
1261         }
1262     }
1263 
1264     if (!g_successReportFlag) {
1265         ExecuteSuccessCacheList();
1266     }
1267 }
1268 
AddSuccessListCache(EventFwk::Want & want,int32_t eventCode)1269 void NotificationAnalyticsUtil::AddSuccessListCache(EventFwk::Want& want, int32_t eventCode)
1270 {
1271     std::lock_guard<ffrt::mutex> lock(reportSuccessCacheMutex_);
1272     int32_t size = static_cast<int32_t>(successReportCacheList.size());
1273     if (size >= SUCCESS_REPORT_CACHE_MAX_SIZE) {
1274         ANS_LOGW("Success list size is max.");
1275         return;
1276     }
1277 
1278     if (reportAggregateTimeId == 0) {
1279         sptr<MiscServices::TimeServiceClient> aggregateTimer = MiscServices::TimeServiceClient::GetInstance();
1280         if (aggregateTimer == nullptr) {
1281             ANS_LOGE("null aggregateTimer");
1282             return;
1283         }
1284         reportAggregateTimeId = aggregateTimer->CreateTimer(reportAggregateTimeInfo);
1285     }
1286 
1287     ReportCache reportCache;
1288     reportCache.want = want;
1289     reportCache.eventCode = eventCode;
1290     successReportCacheList.push_back(reportCache);
1291     if (!g_successReportFlag) {
1292         ExecuteSuccessCacheList();
1293     }
1294 }
1295 
Aggregate()1296 ReportCache NotificationAnalyticsUtil::Aggregate()
1297 {
1298     ANS_LOGD("called");
1299     EventFwk::Want want;
1300     auto reportCachetemp = successReportCacheList.front();
1301 
1302     std::shared_ptr<AAFwk::WantParams> extraInfo = std::make_shared<AAFwk::WantParams>();
1303     AAFwk::WantParamWrapper wWrapper(*extraInfo);
1304     std::string extralInfoStr = wWrapper.ToString();
1305     want.SetParam("extraInfo", extralInfoStr);
1306     want.SetBundle(reportCachetemp.want.GetBundle());
1307     std::string agentBundleName = reportCachetemp.want.GetStringParam("agentBundleName");
1308     if (!agentBundleName.empty()) {
1309         want.SetParam("agentBundleName", agentBundleName);
1310     }
1311     want.SetAction(NOTIFICATION_EVENT_PUSH_AGENT);
1312 
1313     std::string ansData = reportCachetemp.want.GetStringParam("ansData");
1314     successReportCacheList.pop_front();
1315     int32_t aggreCount = MAX_NUMBER_EVERY_REPORT - 1;
1316     while (aggreCount > 0) {
1317         if (successReportCacheList.empty()) {
1318             break;
1319         }
1320         auto reportCache = successReportCacheList.front();
1321 
1322         ansData += "|" + reportCache.want.GetStringParam("ansData");
1323         successReportCacheList.pop_front();
1324         aggreCount--;
1325     }
1326     want.SetParam("ansData", ansData);
1327     ReportCache reportInfo;
1328     reportInfo.want = want;
1329     reportInfo.eventCode = ANS_CUSTOMIZE_CODE ;
1330     return reportInfo;
1331 }
1332 
ExecuteSuccessCacheList()1333 void NotificationAnalyticsUtil::ExecuteSuccessCacheList()
1334 {
1335     if (successReportCacheList.empty()) {
1336         ANS_LOGI("successReportCacheList is empty");
1337         if (reportAggList.empty()) {
1338             g_successReportFlag = false;
1339             ANS_LOGI("No aggregate data need report");
1340             return;
1341         }
1342     } else {
1343         while (!successReportCacheList.empty()) {
1344             auto reportCache = Aggregate();
1345             reportAggList.emplace_back(reportCache);
1346         }
1347     }
1348 
1349     auto reportCount = MAX_REPORT_COUNT;
1350     while (reportCount > 0 && !reportAggList.empty()) {
1351         auto reportCache = reportAggList.front();
1352         ReportCommonEvent(reportCache);
1353         reportAggList.pop_front();
1354         reportCount--;
1355     }
1356     CheckBadgeReport();
1357     auto triggerFunc = [] {
1358         std::lock_guard<ffrt::mutex> lock(reportSuccessCacheMutex_);
1359         NotificationAnalyticsUtil::ExecuteSuccessCacheList();
1360     };
1361     reportAggregateTimeInfo->SetCallbackInfo(triggerFunc);
1362     sptr<MiscServices::TimeServiceClient> aggregateTimer = MiscServices::TimeServiceClient::GetInstance();
1363     if (aggregateTimer == nullptr || reportAggregateTimeId == 0) {
1364         g_successReportFlag = false;
1365         ANS_LOGE("Failed to start timer due to get TimeServiceClient is null.");
1366         return;
1367     }
1368     aggregateTimer->StartTimer(reportAggregateTimeId, NotificationAnalyticsUtil::GetCurrentTime() +
1369         SUCCESS_REPORT_CACHE_INTERVAL_TIME * NotificationConstant::SECOND_TO_MS);
1370     g_successReportFlag = true;
1371 }
1372 
1373 
ExecuteCacheList()1374 void NotificationAnalyticsUtil::ExecuteCacheList()
1375 {
1376     if (reportCacheList.empty()) {
1377         g_reportFlag = false;
1378         ANS_LOGE("empty reportCacheList");
1379         return;
1380     }
1381     auto reportCache = reportCacheList.front();
1382     ReportCommonEvent(reportCache);
1383     auto triggerFunc = [] {
1384         std::lock_guard<ffrt::mutex> lock(reportCacheMutex_);
1385         NotificationAnalyticsUtil::ExecuteCacheList();
1386     };
1387     reportCacheList.pop_front();
1388     reportTimeInfo->SetCallbackInfo(triggerFunc);
1389     sptr<MiscServices::TimeServiceClient> timer = MiscServices::TimeServiceClient::GetInstance();
1390     if (timer == nullptr || reportTimerId == 0) {
1391         g_reportFlag = false;
1392         ANS_LOGE("null timer or reportTimerId");
1393         return;
1394     }
1395     timer->StartTimer(reportTimerId, NotificationAnalyticsUtil::GetCurrentTime() +
1396         REPORT_CACHE_INTERVAL_TIME * NotificationConstant::SECOND_TO_MS);
1397     g_reportFlag = true;
1398 }
1399 
ReportCommonEvent(const ReportCache & reportCache)1400 void NotificationAnalyticsUtil::ReportCommonEvent(const ReportCache& reportCache)
1401 {
1402     EventFwk::CommonEventPublishInfo publishInfo;
1403     publishInfo.SetSubscriberPermissions({OHOS_PERMISSION_NOTIFICATION_CONTROLLER});
1404     EventFwk::CommonEventData commonData {reportCache.want, reportCache.eventCode, ""};
1405     if (!EventFwk::CommonEventManager::PublishCommonEvent(commonData, publishInfo)) {
1406         ANS_LOGE("Publish event failed %{public}d", reportCache.eventCode);
1407     }
1408 }
1409 
GetCurrentTime()1410 int64_t NotificationAnalyticsUtil::GetCurrentTime()
1411 {
1412     auto now = std::chrono::system_clock::now();
1413     auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch());
1414     return duration.count();
1415 }
1416 
ReportOperationsDotEvent(HaOperationMessage & operationMessage)1417 void NotificationAnalyticsUtil::ReportOperationsDotEvent(HaOperationMessage& operationMessage)
1418 {
1419     if (!operationMessage.DetermineWhetherToSend()) {
1420         return;
1421     }
1422 
1423     if (!ReportFlowControl(ANS_CUSTOMIZE_CODE)) {
1424         ANS_LOGE("Publish event failed, reason:%{public}s", operationMessage.ToJson().c_str());
1425         return;
1426     }
1427     EventFwk::Want want;
1428     HaMetaMessage message;
1429     std::string extraInfo = NotificationAnalyticsUtil::BuildExtraInfo(message);
1430     NotificationAnalyticsUtil::SetCommonWant(want, message, extraInfo);
1431     std::string ansData = operationMessage.ToJson();
1432     want.SetParam("ansData", ansData);
1433     ANS_LOGI("Publish operation event :%{public}s", operationMessage.ToJson().c_str());
1434     operationMessage.ResetData();
1435     IN_PROCESS_CALL_WITHOUT_RET(AddListCache(want, ANS_CUSTOMIZE_CODE));
1436 }
1437 
ReportPublishFailedEvent(const HaMetaMessage & message)1438 void NotificationAnalyticsUtil::ReportPublishFailedEvent(const HaMetaMessage& message)
1439 {
1440     if (!ReportFlowControl(PUBLISH_ERROR_EVENT_CODE)) {
1441         ANS_LOGE("Publish event failed, reason:%{public}s", message.Build().c_str());
1442         return;
1443     }
1444     EventFwk::Want want;
1445     std::string extraInfo = NotificationAnalyticsUtil::BuildExtraInfo(message);
1446     NotificationAnalyticsUtil::SetCommonWant(want, message, extraInfo);
1447 
1448     want.SetParam("typeCode", message.typeCode_);
1449 
1450     IN_PROCESS_CALL_WITHOUT_RET(AddListCache(want, PUBLISH_ERROR_EVENT_CODE));
1451 }
1452 
ReportSkipFailedEvent(const HaMetaMessage & message)1453 void NotificationAnalyticsUtil::ReportSkipFailedEvent(const HaMetaMessage& message)
1454 {
1455     if (!ReportFlowControl(MODIFY_ERROR_EVENT_CODE)) {
1456         ANS_LOGE("Publish event failed, reason:%{public}s", message.Build().c_str());
1457         return;
1458     }
1459     EventFwk::Want want;
1460     std::string extraInfo = NotificationAnalyticsUtil::BuildExtraInfo(message);
1461     NotificationAnalyticsUtil::SetCommonWant(want, message, extraInfo);
1462 
1463     IN_PROCESS_CALL_WITHOUT_RET(AddListCache(want, MODIFY_ERROR_EVENT_CODE));
1464 }
1465 
ReportAllBundlesSlotEnabled()1466 bool NotificationAnalyticsUtil::ReportAllBundlesSlotEnabled()
1467 {
1468     if (!CheckSlotNeedReport()) {
1469         return false;
1470     }
1471 
1472     int32_t userId = SUBSCRIBE_USER_INIT;
1473     OsAccountManagerHelper::GetInstance().GetCurrentActiveUserId(userId);
1474 
1475     if (userId == SUBSCRIBE_USER_INIT) {
1476         ANS_LOGE("userId is failed");
1477         return false;
1478     }
1479 
1480     if (!CreateSlotTimerExecute(userId)) {
1481         return false;
1482     }
1483     return true;
1484 }
1485 
CreateSlotTimerExecute(const int32_t & userId)1486 bool NotificationAnalyticsUtil::CreateSlotTimerExecute(const int32_t &userId)
1487 {
1488     std::lock_guard<ffrt::mutex> lock(reportSlotEnabledMutex_);
1489     if (g_reportSlotFlag) {
1490         ANS_LOGW("now has message is reporting");
1491         return false;
1492     }
1493 
1494     sptr<MiscServices::TimeServiceClient> timer =
1495         MiscServices::TimeServiceClient::GetInstance();
1496     if (timer == nullptr) {
1497         ANS_LOGE("null timer");
1498         g_reportSlotFlag = false;
1499         return false;
1500     }
1501     if (reportSlotEnabledTimerId_ == 0) {
1502         reportSlotEnabledTimerId_ = timer->CreateTimer(slotTimeInfo);
1503     }
1504 
1505     auto triggerFunc = [userId] {
1506         ANS_LOGI("trigger is arrived, userid:%{public}d", userId);
1507         GetAllSlotMessageCache(userId);
1508         ExecuteSlotReportList();
1509     };
1510 
1511     slotTimeInfo->SetCallbackInfo(triggerFunc);
1512     timer->StartTimer(reportSlotEnabledTimerId_, NotificationAnalyticsUtil::GetCurrentTime() +
1513         DEFAULT_ERROR_EVENT_TIME * NotificationConstant::SECOND_TO_MS);
1514     g_reportSlotFlag = true;
1515     return true;
1516 }
1517 
ExecuteSlotReportList()1518 void NotificationAnalyticsUtil::ExecuteSlotReportList()
1519 {
1520     std::lock_guard<ffrt::mutex> lock(reportSlotEnabledMutex_);
1521 
1522     if (!ReportSlotEnable()) {
1523         g_reportSlotFlag = false;
1524         return;
1525     }
1526 
1527     sptr<MiscServices::TimeServiceClient> timer = MiscServices::TimeServiceClient::GetInstance();
1528     if (timer == nullptr) {
1529         ANS_LOGE("null timer");
1530         g_reportSlotFlag = false;
1531         return;
1532     }
1533     auto triggerFunc = [] {
1534         ExecuteSlotReportList();
1535     };
1536 
1537     slotTimeInfo->SetCallbackInfo(triggerFunc);
1538     timer->StartTimer(reportSlotEnabledTimerId_, NotificationAnalyticsUtil::GetCurrentTime() +
1539         DEFAULT_ERROR_EVENT_TIME * NotificationConstant::SECOND_TO_MS);
1540     g_reportSlotFlag = true;
1541 }
1542 
ReportSlotEnable()1543 bool NotificationAnalyticsUtil::ReportSlotEnable()
1544 {
1545     std::lock_guard<ffrt::mutex> lock(slotEnabledListMutex_);
1546     if (slotEnabledList_.empty()) {
1547         ANS_LOGI("report end");
1548         return false;
1549     }
1550 
1551     std::list<ReportSlotMessage> slotEnabledReportList;
1552     int count = SLOT_ONCE_REPORT;
1553     while (count-- > 0 && !slotEnabledList_.empty()) {
1554         auto slotMessage = slotEnabledList_.front();
1555         slotEnabledReportList.push_back(slotMessage);
1556         slotEnabledList_.pop_front();
1557     }
1558 
1559     ReportCache reportCache;
1560     BuildSlotReportCache(reportCache, slotEnabledReportList);
1561     ReportCommonEvent(reportCache);
1562     return true;
1563 }
1564 
BuildSlotReportCache(ReportCache & reportCache,std::list<ReportSlotMessage> & slotEnabledReportList)1565 bool NotificationAnalyticsUtil::BuildSlotReportCache(ReportCache &reportCache,
1566     std::list<ReportSlotMessage> &slotEnabledReportList)
1567 {
1568     nlohmann::json ansData;
1569     ansData["subCode"] = std::to_string(SLOT_SUB_CODE);
1570     nlohmann::json dataArray;
1571     for (const auto &report : slotEnabledReportList) {
1572         nlohmann::json dataItem;
1573         dataItem["slotType"] = report.slotType;
1574         dataItem["status"] = report.status;
1575         dataItem["bundleName"] = report.bundleName;
1576         dataItem["uid"] = report.uid;
1577         dataArray.push_back(dataItem);
1578     }
1579     ansData["data"] = dataArray;
1580 
1581     std::string message = ansData.dump(-1, ' ', false,
1582         nlohmann::json::error_handler_t::replace);
1583     EventFwk::Want want;
1584     want.SetAction(NOTIFICATION_EVENT_PUSH_AGENT);
1585     want.SetParam("ansData", message);
1586 
1587     reportCache.want = want;
1588     reportCache.eventCode = ANS_CUSTOMIZE_CODE;
1589     return true;
1590 }
1591 
CheckSlotNeedReport()1592 bool NotificationAnalyticsUtil::CheckSlotNeedReport()
1593 {
1594     std::lock_guard<ffrt::mutex> lock(lastReportTimeMutex_);
1595     auto now = GetCurrentTime();
1596     if (lastReportTime_ != 0 && abs(now - lastReportTime_) <= SLOT_REPORT_INTERVAL) {
1597         ANS_LOGD("no need report");
1598         return false;
1599     }
1600 
1601     ANS_LOGI("slot enabled need report");
1602     lastReportTime_ = now;
1603     return true;
1604 }
1605 
GetAllSlotMessageCache(const int32_t & userId)1606 bool NotificationAnalyticsUtil::GetAllSlotMessageCache(const int32_t &userId)
1607 {
1608     std::unordered_map<std::string, std::string> slotEnablesMap;
1609     auto res = NotificationPreferences::GetInstance()->GetBatchKvsFromDbContainsKey(
1610         LIVE_VIEW_SLOT_ENABLE_END, slotEnablesMap, userId);
1611     if (res != ERR_OK) {
1612         ANS_LOGW("message is err:%{public}d, userId:%{public}d ", res, userId);
1613         return false;
1614     }
1615 
1616     if (slotEnablesMap.size() == 0 || slotEnablesMap.size() > SLOT_MAX_REPORT) {
1617         ANS_LOGW("slotEnablesMap size %{public}zu", slotEnablesMap.size());
1618         return false;
1619     }
1620     std::lock_guard<ffrt::mutex> lock(slotEnabledListMutex_);
1621     for (const auto& budleEntry : slotEnablesMap) {
1622         std::string budleEntryKey = budleEntry.first;
1623         // enable
1624         ReportSlotMessage reportSlotMessage;
1625         std::string budleEntryValue = budleEntry.second;
1626         NotificationAnalyticsUtil::GetReportSlotMessage(budleEntryKey,
1627             budleEntryValue, reportSlotMessage, userId);
1628         slotEnabledList_.push_back(reportSlotMessage);
1629     }
1630     return true;
1631 }
1632 
GetReportSlotMessage(std::string & budleEntryKey,std::string & budleEntryValue,ReportSlotMessage & reportSlotMessage,const int32_t & userId)1633 bool NotificationAnalyticsUtil::GetReportSlotMessage(std::string& budleEntryKey,
1634     std::string& budleEntryValue, ReportSlotMessage& reportSlotMessage, const int32_t &userId)
1635 {
1636     // find first
1637     size_t firstUnderscore = budleEntryKey.find('_');
1638     // find second
1639     size_t secondUnderscore = budleEntryKey.find('_', firstUnderscore + 1);
1640     // find third
1641     size_t thirdUnderscore = budleEntryKey.find('_', secondUnderscore + 1);
1642     // get bundle string
1643     std::string extracted = budleEntryKey.substr(secondUnderscore + 1, thirdUnderscore - secondUnderscore - 1);
1644 
1645     std::unordered_map<std::string, std::string> bundleInfoMap;
1646     auto res = NotificationPreferences::GetInstance()->GetBatchKvsFromDbContainsKey(
1647         extracted, bundleInfoMap, userId);
1648     if (res != ERR_OK) {
1649         ANS_LOGW("get bundleInfoMap is err:%{public}d", res);
1650         return false;
1651     }
1652 
1653     auto nameIt = bundleInfoMap.find(ANS_BUNDLE_BEGIN + LINE + extracted + LINE + NAME);
1654     auto uidIt = bundleInfoMap.find(ANS_BUNDLE_BEGIN + LINE + extracted + LINE + UID);
1655     if (nameIt == bundleInfoMap.end() || uidIt == bundleInfoMap.end()) {
1656         ANS_LOGW("bundleInfoMap is empty, database error");
1657         return false;
1658     }
1659 
1660     // data process
1661     std::string bundleName = nameIt->second;
1662     int32_t uid = std::atoi(uidIt->second.c_str());
1663     bool enable = std::atoi(budleEntryValue.c_str());
1664     ANS_LOGI("budleInfoEntry uid %{public}d, name is:%{public}s, enabled:%{public}d",
1665         uid, bundleName.c_str(), enable);
1666     reportSlotMessage.uid = uid;
1667     reportSlotMessage.status = enable;
1668     reportSlotMessage.slotType = static_cast<int32_t>(
1669         NotificationConstant::SlotType::LIVE_VIEW);
1670     reportSlotMessage.bundleName = bundleName;
1671     return true;
1672 }
1673 } // namespace Notification
1674 } // namespace OHOS
1675