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