• 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 
32 namespace OHOS {
33 namespace Notification {
34 constexpr char MESSAGE_DELIMITER = '#';
35 constexpr const int32_t PUBLISH_ERROR_EVENT_CODE = 0;
36 constexpr const int32_t DELETE_ERROR_EVENT_CODE = 5;
37 constexpr const int32_t MODIFY_ERROR_EVENT_CODE = 6;
38 constexpr const int32_t ANS_CUSTOMIZE_CODE = 7;
39 
40 constexpr const int32_t DEFAULT_ERROR_EVENT_COUNT = 5;
41 constexpr const int32_t DEFAULT_ERROR_EVENT_TIME = 60;
42 constexpr const int32_t MODIFY_ERROR_EVENT_COUNT = 6;
43 constexpr const int32_t MODIFY_ERROR_EVENT_TIME = 60;
44 constexpr const int32_t MAX_NUMBER_EVERY_REPORT = 20;
45 constexpr const int32_t MAX_REPORT_COUNT = 3;
46 
47 constexpr const int32_t REPORT_CACHE_MAX_SIZE = 50;
48 constexpr const int32_t SUCCESS_REPORT_CACHE_MAX_SIZE = 60;
49 constexpr const int32_t REPORT_CACHE_INTERVAL_TIME = 30;
50 constexpr const int32_t SUCCESS_REPORT_CACHE_INTERVAL_TIME = 1800;
51 constexpr const int32_t REASON_MAX_LENGTH = 127;
52 
53 constexpr const int32_t SOUND_FLAG = 1 << 10;
54 constexpr const int32_t LOCKSCREEN_FLAG = 1 << 11;
55 constexpr const int32_t BANNER_FLAG = 1 << 12;
56 constexpr const int32_t VIBRATION_FLAG = 1 << 13;
57 
58 const static std::string NOTIFICATION_EVENT_PUSH_AGENT = "notification.event.PUSH_AGENT";
59 static std::mutex reportFlowControlMutex_;
60 static std::map<int32_t, std::list<std::chrono::system_clock::time_point>> flowControlTimestampMap_ = {
61     {MODIFY_ERROR_EVENT_CODE, {}},
62     {PUBLISH_ERROR_EVENT_CODE, {}},
63     {DELETE_ERROR_EVENT_CODE, {}},
64 };
65 
66 static std::mutex reportCacheMutex_;
67 static uint64_t reportTimerId = 0;
68 static std::list<ReportCache> reportCacheList;
69 static bool g_reportFlag = false;
70 static std::shared_ptr<ReportTimerInfo> reportTimeInfo = std::make_shared<ReportTimerInfo>();
71 
72 static std::mutex reportSuccessCacheMutex_;
73 static uint64_t reportSuccessTimerId = 0;
74 static std::list<ReportCache> successReportCacheList;
75 static bool g_successReportFlag = false;
76 static std::shared_ptr<ReportTimerInfo> reportSuccessTimeInfo = std::make_shared<ReportTimerInfo>();
77 
HaMetaMessage(uint32_t sceneId,uint32_t branchId)78 HaMetaMessage::HaMetaMessage(uint32_t sceneId, uint32_t branchId)
79     : sceneId_(sceneId), branchId_(branchId)
80 {
81 }
82 
NeedReport() const83 bool HaMetaMessage::NeedReport() const
84 {
85     if (errorCode_ == ERR_OK && checkfailed_) {
86         return false;
87     }
88     return true;
89 }
90 
SceneId(uint32_t sceneId)91 HaMetaMessage& HaMetaMessage::SceneId(uint32_t sceneId)
92 {
93     sceneId_ = sceneId;
94     return *this;
95 }
96 
BranchId(uint32_t branchId)97 HaMetaMessage& HaMetaMessage::BranchId(uint32_t branchId)
98 {
99     branchId_ = branchId;
100     return *this;
101 }
102 
ErrorCode(uint32_t errorCode)103 HaMetaMessage& HaMetaMessage::ErrorCode(uint32_t errorCode)
104 {
105     errorCode_ = errorCode;
106     return *this;
107 }
108 
Message(const std::string & message,bool print)109 HaMetaMessage& HaMetaMessage::Message(const std::string& message, bool print)
110 {
111     message_ = message;
112     if (print) {
113         ANSR_LOGE("%{public}s, %{public}d", message.c_str(), errorCode_);
114     }
115     return *this;
116 }
117 
Append(const std::string & message)118 HaMetaMessage& HaMetaMessage::Append(const std::string& message)
119 {
120     message_+=message;
121     return *this;
122 }
Checkfailed(bool checkfailed)123 HaMetaMessage& HaMetaMessage::Checkfailed(bool checkfailed)
124 {
125     checkfailed_ = checkfailed;
126     return *this;
127 }
128 
BundleName(const std::string & bundleName)129 HaMetaMessage& HaMetaMessage::BundleName(const std::string& bundleName)
130 {
131     bundleName_ = bundleName;
132     return *this;
133 }
134 
AgentBundleName(const std::string & agentBundleName)135 HaMetaMessage& HaMetaMessage::AgentBundleName(const std::string& agentBundleName)
136 {
137     agentBundleName_ = agentBundleName;
138     return *this;
139 }
140 
TypeCode(int32_t typeCode)141 HaMetaMessage& HaMetaMessage::TypeCode(int32_t typeCode)
142 {
143     typeCode_ = typeCode;
144     return *this;
145 }
146 
NotificationId(int32_t notificationId)147 HaMetaMessage& HaMetaMessage::NotificationId(int32_t notificationId)
148 {
149     notificationId_ = notificationId;
150     return *this;
151 }
152 
GetMessage() const153 std::string HaMetaMessage::GetMessage() const
154 {
155     return message_;
156 }
157 
SlotType(int32_t slotType)158 HaMetaMessage& HaMetaMessage::SlotType(int32_t slotType)
159 {
160     slotType_ = static_cast<uint32_t>(slotType);
161     return *this;
162 }
163 
Build() const164 std::string HaMetaMessage::Build() const
165 {
166     return std::to_string(sceneId_) + MESSAGE_DELIMITER +
167         std::to_string(branchId_) + MESSAGE_DELIMITER + std::to_string(errorCode_) +
168         MESSAGE_DELIMITER + message_ + MESSAGE_DELIMITER;
169 }
170 
ReportPublishFailedEvent(const sptr<NotificationRequest> & request,const HaMetaMessage & message)171 void NotificationAnalyticsUtil::ReportPublishFailedEvent(const sptr<NotificationRequest>& request,
172     const HaMetaMessage& message)
173 {
174     CommonNotificationEvent(request, PUBLISH_ERROR_EVENT_CODE, message);
175 }
176 
ReportDeleteFailedEvent(const sptr<NotificationRequest> & request,HaMetaMessage & message)177 void NotificationAnalyticsUtil::ReportDeleteFailedEvent(const sptr<NotificationRequest>& request,
178     HaMetaMessage& message)
179 {
180     if (request == nullptr || !message.NeedReport()) {
181         ANS_LOGE("request is null %{public}d", message.NeedReport());
182         return;
183     }
184     std::shared_ptr<NotificationBundleOption> agentBundleNameOption = request->GetAgentBundle();
185     if (agentBundleNameOption != nullptr) {
186         std::string agentBundleName = agentBundleNameOption->GetBundleName();
187         if (!agentBundleName.empty()) {
188             message = message.AgentBundleName(agentBundleName);
189         }
190     }
191 }
192 
CommonNotificationEvent(const sptr<NotificationRequest> & request,int32_t eventCode,const HaMetaMessage & message)193 void NotificationAnalyticsUtil::CommonNotificationEvent(const sptr<NotificationRequest>& request,
194     int32_t eventCode, const HaMetaMessage& message)
195 {
196     if (request == nullptr) {
197         return;
198     }
199 
200     if (!ReportFlowControl(eventCode)) {
201         ANS_LOGI("Publish event failed, eventCode:%{public}d, reason:%{public}s",
202             eventCode, message.Build().c_str());
203         return;
204     }
205     EventFwk::Want want;
206     std::string extraInfo = NotificationAnalyticsUtil::BuildExtraInfoWithReq(message, request);
207     NotificationAnalyticsUtil::SetCommonWant(want, message, extraInfo);
208 
209     want.SetParam("typeCode", message.typeCode_);
210     IN_PROCESS_CALL_WITHOUT_RET(ReportNotificationEvent(
211         request, want, eventCode, message.Build()));
212 }
213 
ReportNotificationEvent(const sptr<NotificationRequest> & request,EventFwk::Want want,int32_t eventCode,const std::string & reason)214 void NotificationAnalyticsUtil::ReportNotificationEvent(const sptr<NotificationRequest>& request,
215     EventFwk::Want want, int32_t eventCode, const std::string& reason)
216 {
217     NotificationNapi::SlotType slotType;
218     NotificationNapi::AnsEnumUtil::SlotTypeCToJS(
219         static_cast<NotificationConstant::SlotType>(request->GetSlotType()), slotType);
220     NotificationNapi::ContentType contentType;
221     NotificationNapi::AnsEnumUtil::ContentTypeCToJS(
222         static_cast<NotificationContent::Type>(request->GetNotificationType()), contentType);
223 
224     want.SetParam("id", request->GetNotificationId());
225     want.SetParam("uid", request->GetOwnerUid());
226     want.SetParam("slotType", static_cast<int32_t>(slotType));
227     want.SetParam("contentType", std::to_string(static_cast<int32_t>(contentType)));
228 
229     if (!request->GetCreatorBundleName().empty()) {
230         want.SetParam("agentBundleName", request->GetCreatorBundleName());
231     }
232     if (!request->GetOwnerBundleName().empty()) {
233         want.SetBundle(request->GetOwnerBundleName());
234     }
235     IN_PROCESS_CALL_WITHOUT_RET(AddListCache(want, eventCode));
236 }
237 
ReportModifyEvent(const HaMetaMessage & message)238 void NotificationAnalyticsUtil::ReportModifyEvent(const HaMetaMessage& message)
239 {
240     if (!ReportFlowControl(MODIFY_ERROR_EVENT_CODE)) {
241         ANS_LOGI("Publish event failed, reason:%{public}s", message.Build().c_str());
242         return;
243     }
244     EventFwk::Want want;
245     std::string extraInfo = NotificationAnalyticsUtil::BuildExtraInfo(message);
246     NotificationAnalyticsUtil::SetCommonWant(want, message, extraInfo);
247 
248     std::string bundle;
249     int32_t callingUid = IPCSkeleton::GetCallingUid();
250     std::shared_ptr<BundleManagerHelper> bundleManager = BundleManagerHelper::GetInstance();
251     if (bundleManager != nullptr) {
252         bundle = bundleManager->GetBundleNameByUid(callingUid);
253     }
254     want.SetBundle(bundle + "_" + std::to_string(callingUid));
255     want.SetParam("slotType", static_cast<int32_t>(message.slotType_));
256     IN_PROCESS_CALL_WITHOUT_RET(AddListCache(want, MODIFY_ERROR_EVENT_CODE));
257 }
258 
ReportDeleteFailedEvent(const HaMetaMessage & message)259 void NotificationAnalyticsUtil::ReportDeleteFailedEvent(const HaMetaMessage& message)
260 {
261     if (!ReportFlowControl(DELETE_ERROR_EVENT_CODE)) {
262         ANS_LOGI("Publish event failed, reason:%{public}s", message.Build().c_str());
263         return;
264     }
265     EventFwk::Want want;
266     std::string extraInfo = NotificationAnalyticsUtil::BuildExtraInfo(message);
267     NotificationAnalyticsUtil::SetCommonWant(want, message, extraInfo);
268 
269     want.SetParam("agentBundleName", message.agentBundleName_);
270     want.SetParam("typeCode", message.typeCode_);
271     want.SetParam("id", message.notificationId_);
272 
273     IN_PROCESS_CALL_WITHOUT_RET(AddListCache(want, DELETE_ERROR_EVENT_CODE));
274 }
275 
ReportPublishSuccessEvent(const sptr<NotificationRequest> & request,const HaMetaMessage & message)276 void NotificationAnalyticsUtil::ReportPublishSuccessEvent(const sptr<NotificationRequest>& request,
277     const HaMetaMessage& message)
278 {
279     ANS_LOGD("ReportPublishSuccessEvent enter");
280     if (request == nullptr) {
281         return;
282     }
283     if (!IsAllowedBundle(request)) {
284         ANS_LOGW("This Bundle not allowed.");
285         return;
286     }
287 
288     EventFwk::Want want;
289     if (!request->GetOwnerBundleName().empty()) {
290         want.SetBundle(request->GetOwnerBundleName());
291     }
292     if (!request->GetCreatorBundleName().empty()) {
293         want.SetParam("agentBundleName", request->GetCreatorBundleName());
294     }
295     std::string ansData = NotificationAnalyticsUtil::BuildAnsData(request, message);
296     want.SetParam("ansData", ansData);
297 
298     IN_PROCESS_CALL_WITHOUT_RET(AddSuccessListCache(want, ANS_CUSTOMIZE_CODE));
299 }
300 
IsAllowedBundle(const sptr<NotificationRequest> & request)301 bool NotificationAnalyticsUtil::IsAllowedBundle(const sptr<NotificationRequest>& request)
302 {
303     ANS_LOGD("IsAllowedBundle enter");
304     std::string bundleName = request->GetOwnerBundleName();
305     return DelayedSingleton<NotificationConfigParse>::GetInstance()->IsReportTrustList(bundleName);
306 }
307 
BuildAnsData(const sptr<NotificationRequest> & request,const HaMetaMessage & message)308 std::string NotificationAnalyticsUtil::BuildAnsData(const sptr<NotificationRequest>& request,
309     const HaMetaMessage& message)
310 {
311     ANS_LOGD("BuildAnsData enter.");
312     nlohmann::json ansData;
313     std::shared_ptr<AAFwk::WantParams> extraInfo = nullptr;
314     if (request->GetUnifiedGroupInfo() != nullptr &&
315         request->GetUnifiedGroupInfo()->GetExtraInfo() != nullptr) {
316         extraInfo = request->GetUnifiedGroupInfo()->GetExtraInfo();
317     } else {
318         extraInfo = std::make_shared<AAFwk::WantParams>();
319     }
320     nlohmann::json extraInfoJson;
321     std::string msgId = extraInfo->GetWantParams("pushData").GetStringParam("msgId");
322     if (!msgId.empty()) {
323         extraInfoJson["msgId"] = msgId;
324     }
325     std::string uniqMsgId = extraInfo->GetWantParams("pushData").GetStringParam("mcMsgId");
326     if (!uniqMsgId.empty()) {
327         extraInfoJson["mcMsgId"] = uniqMsgId;
328     }
329 
330     ansData["extraInfo"] = extraInfoJson.dump(-1, ' ', false, nlohmann::json::error_handler_t::replace);
331     ansData["uid"] = std::to_string(request->GetOwnerUid());
332     ansData["id"] = std::to_string(request->GetNotificationId());
333     NotificationNapi::SlotType slotType;
334     NotificationNapi::AnsEnumUtil::SlotTypeCToJS(
335         static_cast<NotificationConstant::SlotType>(request->GetSlotType()), slotType);
336     NotificationNapi::ContentType contentType;
337     NotificationNapi::AnsEnumUtil::ContentTypeCToJS(
338         static_cast<NotificationContent::Type>(request->GetNotificationType()), contentType);
339     ansData["slotType"] = static_cast<int32_t>(slotType);
340     ansData["contentType"] = std::to_string(static_cast<int32_t>(contentType));
341     ansData["reminderFlags"] = std::to_string(static_cast<int32_t>(request->GetFlags()->GetReminderFlags()));
342     uint32_t controlFlags = request->GetNotificationControlFlags();
343     std::shared_ptr<NotificationFlags> tempFlags = request->GetFlags();
344     ansData["ControlFlags"] = SetControlFlags(tempFlags, controlFlags);
345     ansData["class"] = request->GetClassification();
346     ansData["deviceStatus"] = GetDeviceStatus(request);
347     ANS_LOGI("Report success, the controlFlags is %{public}d, deviceStatus is %{public}s",
348         controlFlags, GetDeviceStatus(request).c_str());
349     return ansData.dump(-1, ' ', false, nlohmann::json::error_handler_t::replace);
350 }
351 
GetDeviceStatus(const sptr<NotificationRequest> & request)352 std::string NotificationAnalyticsUtil::GetDeviceStatus(const sptr<NotificationRequest>& request)
353 {
354     std::map<std::string, std::string> deviceStatus = request->GetdeviceStatus();
355     nlohmann::json deviceStatusJson;
356     for (map<string, string>::const_iterator iter = deviceStatus.begin(); iter != deviceStatus.end(); ++iter) {
357         deviceStatusJson[iter->first] = iter->second;
358     }
359     return deviceStatusJson.dump(-1, ' ', false, nlohmann::json::error_handler_t::replace);
360 }
SetControlFlags(const std::shared_ptr<NotificationFlags> & flags,uint32_t controlFlags)361 uint32_t NotificationAnalyticsUtil::SetControlFlags(const std::shared_ptr<NotificationFlags> &flags,
362     uint32_t controlFlags)
363 {
364     if (flags->IsSoundEnabled() == NotificationConstant::FlagStatus::OPEN) {
365         controlFlags |= SOUND_FLAG;
366     } else {
367         controlFlags &= ~SOUND_FLAG;
368     }
369     if (flags->IsVibrationEnabled() == NotificationConstant::FlagStatus::OPEN) {
370         controlFlags |= VIBRATION_FLAG;
371     } else {
372         controlFlags &= ~VIBRATION_FLAG;
373     }
374     if (flags->IsLockScreenVisblenessEnabled()) {
375         controlFlags |= LOCKSCREEN_FLAG;
376     } else {
377         controlFlags &= ~LOCKSCREEN_FLAG;
378     }
379     if (flags->IsBannerEnabled()) {
380         controlFlags |= BANNER_FLAG;
381     } else {
382         controlFlags &= ~BANNER_FLAG;
383     }
384     return controlFlags;
385 }
ReportNotificationEvent(EventFwk::Want want,int32_t eventCode,const std::string & reason)386 void NotificationAnalyticsUtil::ReportNotificationEvent(EventFwk::Want want,
387     int32_t eventCode, const std::string& reason)
388 {
389     EventFwk::CommonEventPublishInfo publishInfo;
390     publishInfo.SetSubscriberPermissions({OHOS_PERMISSION_NOTIFICATION_AGENT_CONTROLLER});
391     EventFwk::CommonEventData commonData {want, eventCode, ""};
392     ANS_LOGD("Publish event success %{public}d, %{public}s", eventCode, reason.c_str());
393     if (!EventFwk::CommonEventManager::PublishCommonEvent(commonData, publishInfo)) {
394         ANS_LOGE("Publish event failed %{public}d, %{public}s", eventCode, reason.c_str());
395     }
396 }
397 
ReportFlowControl(const int32_t reportType)398 bool NotificationAnalyticsUtil::ReportFlowControl(const int32_t reportType)
399 {
400     std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
401     std::lock_guard<std::mutex> lock(reportFlowControlMutex_);
402     auto iter = flowControlTimestampMap_.find(reportType);
403     if (iter == flowControlTimestampMap_.end()) {
404         return false;
405     }
406     auto& list = iter->second;
407     FlowControllerOption option = GetFlowOptionByType(reportType);
408     RemoveExpired(list, now, option.time);
409     int32_t size = list.size();
410     int32_t count = option.count;
411     if (size >= count) {
412         return false;
413     }
414     list.push_back(now);
415     return true;
416 }
417 
RemoveExpired(std::list<std::chrono::system_clock::time_point> & list,const std::chrono::system_clock::time_point & now,int32_t time)418 void NotificationAnalyticsUtil::RemoveExpired(std::list<std::chrono::system_clock::time_point> &list,
419     const std::chrono::system_clock::time_point &now, int32_t time)
420 {
421     auto iter = list.begin();
422     while (iter != list.end()) {
423         if (abs(now - *iter) > std::chrono::seconds(time)) {
424             iter = list.erase(iter);
425         } else {
426             break;
427         }
428     }
429 }
430 
GetFlowOptionByType(const int32_t reportType)431 FlowControllerOption NotificationAnalyticsUtil::GetFlowOptionByType(const int32_t reportType)
432 {
433     FlowControllerOption option;
434     switch (reportType) {
435         case MODIFY_ERROR_EVENT_CODE:
436             option.count = MODIFY_ERROR_EVENT_COUNT;
437             option.time = MODIFY_ERROR_EVENT_TIME;
438             break;
439         default:
440             option.count = DEFAULT_ERROR_EVENT_COUNT;
441             option.time = DEFAULT_ERROR_EVENT_TIME;
442             break;
443     }
444     return option;
445 }
446 
BuildExtraInfo(const HaMetaMessage & message)447 std::string NotificationAnalyticsUtil::BuildExtraInfo(const HaMetaMessage& message)
448 {
449     nlohmann::json reason;
450     reason["scene"] = message.sceneId_;
451     reason["branch"] = message.branchId_;
452     reason["innerErr"] = message.errorCode_;
453     reason["detail"] = message.message_;
454 
455     auto now = std::chrono::duration_cast<std::chrono::milliseconds>(
456         std::chrono::system_clock::now().time_since_epoch()).count();
457     reason["time"] = now;
458 
459     std::shared_ptr<AAFwk::WantParams> extraInfo = std::make_shared<AAFwk::WantParams>();
460 
461     reason["detail"] = "";
462     int32_t reasonFixedSize =
463         static_cast<int32_t>(reason.dump(-1, ' ', false, nlohmann::json::error_handler_t::replace).size());
464     int32_t leftSpace = REASON_MAX_LENGTH - reasonFixedSize;
465     if (leftSpace < 0) {
466         std::string basicInfo = std::to_string(message.sceneId_) + MESSAGE_DELIMITER +
467             std::to_string(message.branchId_) + MESSAGE_DELIMITER +
468             std::to_string(message.errorCode_) + MESSAGE_DELIMITER +
469             std::to_string(now) + " Reason fixed size exceeds limit";
470         extraInfo->SetParam("reason", AAFwk::String::Box(basicInfo));
471         ANS_LOGI("%{public}s", basicInfo.c_str());
472     } else {
473         reason["detail"] = message.message_.substr(0, leftSpace);
474         extraInfo->SetParam("reason",
475             AAFwk::String::Box(reason.dump(-1, ' ', false, nlohmann::json::error_handler_t::replace)));
476     }
477 
478     AAFwk::WantParamWrapper wWrapper(*extraInfo);
479 
480     return wWrapper.ToString();
481 }
482 
BuildExtraInfoWithReq(const HaMetaMessage & message,const sptr<NotificationRequest> & request)483 std::string NotificationAnalyticsUtil::BuildExtraInfoWithReq(const HaMetaMessage& message,
484     const sptr<NotificationRequest>& request)
485 {
486     NotificationNapi::ContentType contentType;
487     NotificationNapi::AnsEnumUtil::ContentTypeCToJS(
488         static_cast<NotificationContent::Type>(request->GetNotificationType()), contentType);
489     nlohmann::json reason;
490     if (contentType == NotificationNapi::ContentType::NOTIFICATION_CONTENT_LIVE_VIEW) {
491         auto content = request->GetContent()->GetNotificationContent();
492         auto liveViewContent = std::static_pointer_cast<NotificationLiveViewContent>(content);
493         reason["status"] = static_cast<int32_t>(liveViewContent->GetLiveViewStatus());
494     }
495 
496     reason["scene"] = message.sceneId_;
497     reason["branch"] = message.branchId_;
498     reason["innerErr"] = message.errorCode_;
499     reason["detail"] = message.message_;
500 
501     auto now = std::chrono::duration_cast<std::chrono::milliseconds>(
502         std::chrono::system_clock::now().time_since_epoch()).count();
503     reason["time"] = now;
504 
505     std::shared_ptr<AAFwk::WantParams> extraInfo = nullptr;
506     if (request->GetUnifiedGroupInfo() != nullptr &&
507         request->GetUnifiedGroupInfo()->GetExtraInfo() != nullptr) {
508         extraInfo = request->GetUnifiedGroupInfo()->GetExtraInfo();
509     } else {
510         extraInfo = std::make_shared<AAFwk::WantParams>();
511     }
512 
513     reason["detail"] = "";
514     int32_t reasonFixedSize =
515         static_cast<int32_t>(reason.dump(-1, ' ', false, nlohmann::json::error_handler_t::replace).size());
516     int32_t leftSpace = REASON_MAX_LENGTH - reasonFixedSize;
517     if (leftSpace < 0) {
518         std::string basicInfo = std::to_string(message.sceneId_) + MESSAGE_DELIMITER +
519             std::to_string(message.branchId_) + MESSAGE_DELIMITER +
520             std::to_string(message.errorCode_) + MESSAGE_DELIMITER +
521             std::to_string(now) + " Reason fixed size exceeds limit";
522         extraInfo->SetParam("reason", AAFwk::String::Box(basicInfo));
523         ANS_LOGI("%{public}s", basicInfo.c_str());
524     } else {
525         reason["detail"] = message.message_.substr(0, leftSpace);
526         extraInfo->SetParam("reason",
527             AAFwk::String::Box(reason.dump(-1, ' ', false, nlohmann::json::error_handler_t::replace)));
528     }
529 
530     AAFwk::WantParamWrapper wWrapper(*extraInfo);
531 
532     return wWrapper.ToString();
533 }
534 
SetCommonWant(EventFwk::Want & want,const HaMetaMessage & message,std::string & extraInfo)535 void NotificationAnalyticsUtil::SetCommonWant(EventFwk::Want& want, const HaMetaMessage& message,
536     std::string& extraInfo)
537 {
538     want.SetBundle(message.bundleName_);
539     want.SetParam("extraInfo", extraInfo);
540     want.SetAction(NOTIFICATION_EVENT_PUSH_AGENT);
541 }
542 
AddListCache(EventFwk::Want & want,int32_t eventCode)543 void NotificationAnalyticsUtil::AddListCache(EventFwk::Want& want, int32_t eventCode)
544 {
545     std::lock_guard<std::mutex> lock(reportCacheMutex_);
546     int32_t size = static_cast<int32_t>(reportCacheList.size());
547     if (size >= REPORT_CACHE_MAX_SIZE) {
548         ANS_LOGW("list size is max");
549         return;
550     }
551 
552     if (reportTimerId == 0) {
553         sptr<MiscServices::TimeServiceClient> timer = MiscServices::TimeServiceClient::GetInstance();
554         if (timer == nullptr) {
555             ANS_LOGE("Failed to start timer due to get TimeServiceClient is null.");
556             return;
557         }
558         reportTimerId = timer->CreateTimer(reportTimeInfo);
559     }
560 
561     ReportCache reportCache;
562     reportCache.want = want;
563     reportCache.eventCode = eventCode;
564     reportCacheList.push_back(reportCache);
565     if (!g_reportFlag) {
566         ExecuteCacheList();
567     }
568 }
569 
AddSuccessListCache(EventFwk::Want & want,int32_t eventCode)570 void NotificationAnalyticsUtil::AddSuccessListCache(EventFwk::Want& want, int32_t eventCode)
571 {
572     std::lock_guard<std::mutex> lock(reportSuccessCacheMutex_);
573     int32_t size = static_cast<int32_t>(successReportCacheList.size());
574     if (size >= SUCCESS_REPORT_CACHE_MAX_SIZE) {
575         ANS_LOGW("Success list size is max.");
576         return;
577     }
578 
579     if (reportSuccessTimerId == 0) {
580         sptr<MiscServices::TimeServiceClient> successTimer = MiscServices::TimeServiceClient::GetInstance();
581         if (successTimer == nullptr) {
582             ANS_LOGE("Failed to start timer due to get TimeServiceClient is null.");
583             return;
584         }
585         reportSuccessTimerId = successTimer->CreateTimer(reportSuccessTimeInfo);
586     }
587 
588     ReportCache reportCache;
589     reportCache.want = want;
590     reportCache.eventCode = eventCode;
591     successReportCacheList.push_back(reportCache);
592     if (!g_successReportFlag) {
593         ExecuteSuccessCacheList();
594     }
595 }
596 
Aggregate()597 ReportCache NotificationAnalyticsUtil::Aggregate()
598 {
599     ANS_LOGI("Success list aggregated.");
600     EventFwk::Want want;
601     auto reportCachetemp = successReportCacheList.front();
602 
603     std::shared_ptr<AAFwk::WantParams> extraInfo = std::make_shared<AAFwk::WantParams>();
604     AAFwk::WantParamWrapper wWrapper(*extraInfo);
605     std::string extralInfoStr = wWrapper.ToString();
606     want.SetParam("extraInfo", extralInfoStr);
607     want.SetBundle(reportCachetemp.want.GetBundle());
608     std::string agentBundleName = reportCachetemp.want.GetStringParam("agentBundleName");
609     if (!agentBundleName.empty()) {
610         want.SetParam("agentBundleName", agentBundleName);
611     }
612     want.SetAction(NOTIFICATION_EVENT_PUSH_AGENT);
613 
614     std::string ansData = reportCachetemp.want.GetStringParam("ansData");
615     successReportCacheList.pop_front();
616     int32_t aggreCount = MAX_NUMBER_EVERY_REPORT;
617     while (aggreCount > 0) {
618         if (successReportCacheList.empty()) {
619             break;
620         }
621         auto reportCache = successReportCacheList.front();
622 
623         ansData += "|" + reportCache.want.GetStringParam("ansData");
624         successReportCacheList.pop_front();
625         aggreCount--;
626     }
627     want.SetParam("ansData", ansData);
628     ReportCache reportInfo;
629     reportInfo.want = want;
630     reportInfo.eventCode = ANS_CUSTOMIZE_CODE ;
631     return reportInfo;
632 }
633 
ExecuteSuccessCacheList()634 void NotificationAnalyticsUtil::ExecuteSuccessCacheList()
635 {
636     if (successReportCacheList.empty()) {
637         g_successReportFlag = false;
638         ANS_LOGI("successReportCacheList is end");
639         return;
640     }
641 
642     auto reportCount = MAX_REPORT_COUNT;
643     while (reportCount > 0) {
644         if (successReportCacheList.empty()) {
645             break;
646         }
647         auto reportCache = Aggregate();
648         ReportCommonEvent(reportCache);
649         reportCount--;
650     }
651     auto triggerFunc = [] {
652         std::lock_guard<std::mutex> lock(reportSuccessCacheMutex_);
653         NotificationAnalyticsUtil::ExecuteSuccessCacheList();
654     };
655     reportSuccessTimeInfo->SetCallbackInfo(triggerFunc);
656     sptr<MiscServices::TimeServiceClient> successTimer = MiscServices::TimeServiceClient::GetInstance();
657     if (successTimer == nullptr || reportSuccessTimerId == 0) {
658         g_successReportFlag = false;
659         ANS_LOGE("Failed to start timer due to get TimeServiceClient is null.");
660         return;
661     }
662     successTimer->StartTimer(reportSuccessTimerId, NotificationAnalyticsUtil::GetCurrentTime() +
663         SUCCESS_REPORT_CACHE_INTERVAL_TIME * NotificationConstant::SECOND_TO_MS);
664     g_successReportFlag = true;
665 }
666 
667 
ExecuteCacheList()668 void NotificationAnalyticsUtil::ExecuteCacheList()
669 {
670     if (reportCacheList.empty()) {
671         g_reportFlag = false;
672         ANS_LOGI("reportCacheList is end");
673         return;
674     }
675     auto reportCache = reportCacheList.front();
676     ReportCommonEvent(reportCache);
677     auto triggerFunc = [] {
678         std::lock_guard<std::mutex> lock(reportCacheMutex_);
679         NotificationAnalyticsUtil::ExecuteCacheList();
680     };
681     reportCacheList.pop_front();
682     reportTimeInfo->SetCallbackInfo(triggerFunc);
683     sptr<MiscServices::TimeServiceClient> timer = MiscServices::TimeServiceClient::GetInstance();
684     if (timer == nullptr || reportTimerId == 0) {
685         g_reportFlag = false;
686         ANS_LOGE("Failed to start timer due to get TimeServiceClient is null.");
687         return;
688     }
689     timer->StartTimer(reportTimerId, NotificationAnalyticsUtil::GetCurrentTime() +
690         REPORT_CACHE_INTERVAL_TIME * NotificationConstant::SECOND_TO_MS);
691     g_reportFlag = true;
692 }
693 
ReportCommonEvent(const ReportCache & reportCache)694 void NotificationAnalyticsUtil::ReportCommonEvent(const ReportCache& reportCache)
695 {
696     EventFwk::CommonEventPublishInfo publishInfo;
697     publishInfo.SetSubscriberPermissions({OHOS_PERMISSION_NOTIFICATION_CONTROLLER});
698     EventFwk::CommonEventData commonData {reportCache.want, reportCache.eventCode, ""};
699     if (!EventFwk::CommonEventManager::PublishCommonEvent(commonData, publishInfo)) {
700         ANS_LOGE("Publish event failed %{public}d", reportCache.eventCode);
701     }
702 }
703 
GetCurrentTime()704 int64_t NotificationAnalyticsUtil::GetCurrentTime()
705 {
706     auto now = std::chrono::system_clock::now();
707     auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch());
708     return duration.count();
709 }
710 } // namespace Notification
711 } // namespace OHOS
712