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 <memory>
17
18 #include "notification_config_parse.h"
19
20 #include "ans_log_wrapper.h"
21 #ifdef ENABLE_ANS_ADDITIONAL_CONTROL
22 #include "notification_extension_wrapper.h"
23 #endif
24 #include "notification_slot.h"
25 #include "file_utils.h"
26
27 namespace OHOS {
28 namespace Notification {
NotificationConfigParse()29 NotificationConfigParse::NotificationConfigParse()
30 {
31 if (!FileUtils::GetJsonByFilePath(NOTIFICAITON_CONFIG_FILE, notificationConfigJsons_)) {
32 ANS_LOGE("Failed to get notification config file, fileName: %{public}s.", NOTIFICAITON_CONFIG_FILE);
33 }
34 defaultCurrentSlotReminder_ = {
35 {NotificationConstant::SlotType::SOCIAL_COMMUNICATION, 0b111111},
36 {NotificationConstant::SlotType::SERVICE_REMINDER, 0b111111},
37 {NotificationConstant::SlotType::CONTENT_INFORMATION, 0b000000},
38 {NotificationConstant::SlotType::OTHER, 0b000000},
39 {NotificationConstant::SlotType::LIVE_VIEW, 0b111011},
40 {NotificationConstant::SlotType::CUSTOMER_SERVICE, 0b110001},
41 {NotificationConstant::SlotType::EMERGENCY_INFORMATION, 0b111111}
42 };
43 }
44
GetAppPrivileges(const std::string & bundleName) const45 std::shared_ptr<NotificationAppPrivileges> NotificationConfigParse::GetAppPrivileges(
46 const std::string &bundleName) const
47 {
48 nlohmann::json root;
49 std::string JsonPoint = "/";
50 JsonPoint.append(APP_PRIVILEGES);
51 if (!GetConfigJson(JsonPoint, root)) {
52 ANS_LOGE("Failed to get JsonPoint CCM config file.");
53 return nullptr;
54 }
55 if (!root.contains(APP_PRIVILEGES)) {
56 ANS_LOGW("not found jsonKey appPrivileges");
57 return nullptr;
58 }
59 nlohmann::json affects = root[APP_PRIVILEGES];
60 if (affects.is_null() || affects.empty()) {
61 ANS_LOGE("GetCcmPrivileges failed as invalid ccmPrivileges json.");
62 return nullptr;
63 }
64 for (auto &affect : affects.items()) {
65 if (affect.key() == bundleName) {
66 return std::make_shared<NotificationAppPrivileges>(affect.value());
67 }
68 }
69 return nullptr;
70 }
71
GetConfigJson(const std::string & keyCheck,nlohmann::json & configJson) const72 bool NotificationConfigParse::GetConfigJson(const std::string &keyCheck, nlohmann::json &configJson) const
73 {
74 if (notificationConfigJsons_.size() <= 0) {
75 ANS_LOGE("Failed to get config json cause empty notificationConfigJsons.");
76 return false;
77 }
78 bool ret = false;
79 std::for_each(notificationConfigJsons_.rbegin(), notificationConfigJsons_.rend(),
80 [&keyCheck, &configJson, &ret](const nlohmann::json &json) {
81 if (keyCheck.find("/") == std::string::npos && json.contains(keyCheck)) {
82 configJson = json;
83 ret = true;
84 }
85
86 if (keyCheck.find("/") != std::string::npos) {
87 nlohmann::json::json_pointer keyCheckPoint(keyCheck);
88 if (json.contains(keyCheckPoint)) {
89 configJson = json;
90 ret = true;
91 }
92 }
93 });
94 if (!ret) {
95 ANS_LOGE("Cannot find keyCheck: %{public}s in notificationConfigJsons.", keyCheck.c_str());
96 }
97 return ret;
98 }
99
SetCurrentSlotReminder(std::map<NotificationConstant::SlotType,std::shared_ptr<NotificationFlags>> & currentSlotReminder,NotificationConstant::SlotType & slotType,std::shared_ptr<NotificationFlags> & reminderFlags)100 void NotificationConfigParse::SetCurrentSlotReminder(
101 std::map<NotificationConstant::SlotType, std::shared_ptr<NotificationFlags>> ¤tSlotReminder,
102 NotificationConstant::SlotType &slotType, std::shared_ptr<NotificationFlags> &reminderFlags)
103 {
104 std::lock_guard<std::mutex> lock(slotReminderMutex_);
105 currentSlotReminder[slotType] = reminderFlags;
106 }
107
GetCurrentSlotReminder(std::map<NotificationConstant::SlotType,std::shared_ptr<NotificationFlags>> & currentSlotReminder) const108 bool NotificationConfigParse::GetCurrentSlotReminder(
109 std::map<NotificationConstant::SlotType, std::shared_ptr<NotificationFlags>> ¤tSlotReminder) const
110 {
111 nlohmann::json root;
112 std::string slotJsonPoint = "/";
113 slotJsonPoint.append(CFG_KEY_NOTIFICATION_SERVICE);
114 slotJsonPoint.append("/");
115 slotJsonPoint.append(CFG_KEY_SLOT_TYPE_REMINDER);
116 if (!GetConfigJson(slotJsonPoint, root)) {
117 return false;
118 }
119
120 if (root.find(CFG_KEY_NOTIFICATION_SERVICE) == root.end()) {
121 ANS_LOGE("GetCurrentSlotReminder failed as can not find notificationService.");
122 return false;
123 }
124 nlohmann::json currentDeviceRemindJson = root[CFG_KEY_NOTIFICATION_SERVICE][CFG_KEY_SLOT_TYPE_REMINDER];
125 if (currentDeviceRemindJson.is_null() || !currentDeviceRemindJson.is_array() || currentDeviceRemindJson.empty()) {
126 ANS_LOGE("GetCurrentSlotReminder failed as invalid currentDeviceReminder json.");
127 return false;
128 }
129 for (auto &reminderFilterSlot : currentDeviceRemindJson) {
130 NotificationConstant::SlotType slotType;
131 if (reminderFilterSlot.find(CFG_KEY_NAME) == reminderFilterSlot.end() ||
132 reminderFilterSlot[CFG_KEY_NAME].is_null() ||
133 !reminderFilterSlot[CFG_KEY_NAME].is_string() ||
134 !NotificationSlot::GetSlotTypeByString(reminderFilterSlot[CFG_KEY_NAME].get<std::string>(), slotType)) {
135 continue;
136 }
137
138 std::shared_ptr<NotificationFlags> reminderFlags;
139 if (reminderFilterSlot.find(CFG_KEY_REMINDER_FLAGS) == reminderFilterSlot.end() ||
140 reminderFilterSlot[CFG_KEY_REMINDER_FLAGS].is_null() ||
141 !reminderFilterSlot[CFG_KEY_REMINDER_FLAGS].is_string() ||
142 !NotificationFlags::GetReminderFlagsByString(
143 reminderFilterSlot[CFG_KEY_REMINDER_FLAGS].get<std::string>(), reminderFlags)) {
144 continue;
145 }
146 DelayedSingleton<NotificationConfigParse>::GetInstance()->
147 SetCurrentSlotReminder(currentSlotReminder, slotType, reminderFlags);
148 }
149 if (currentSlotReminder.size() <= 0) {
150 ANS_LOGE("GetCurrentSlotReminder failed as invalid currentSlotReminder size.");
151 return false;
152 }
153 return true;
154 }
155
GetConfigSlotReminderModeByType(NotificationConstant::SlotType slotType) const156 uint32_t NotificationConfigParse::GetConfigSlotReminderModeByType(NotificationConstant::SlotType slotType) const
157 {
158 static std::map<NotificationConstant::SlotType, std::shared_ptr<NotificationFlags>> configSlotsReminder;
159 if (configSlotsReminder.empty()) {
160 GetCurrentSlotReminder(configSlotsReminder);
161 }
162
163 auto iter = configSlotsReminder.find(slotType);
164 if (iter != configSlotsReminder.end()) {
165 return iter->second->GetReminderFlags();
166 }
167
168 auto defaultIter = defaultCurrentSlotReminder_.find(slotType);
169 if (defaultIter != defaultCurrentSlotReminder_.end()) {
170 return defaultIter->second;
171 }
172
173 return 0;
174 }
175
IsLiveViewEnabled(const std::string bundleName) const176 bool NotificationConfigParse::IsLiveViewEnabled(const std::string bundleName) const
177 {
178 std::shared_ptr<NotificationAppPrivileges> appPrivileges = GetAppPrivileges(bundleName);
179 if (appPrivileges == nullptr) {
180 return false;
181 }
182 return appPrivileges->IsLiveViewEnabled();
183 }
184
IsReminderEnabled(const std::string & bundleName) const185 bool NotificationConfigParse::IsReminderEnabled(const std::string& bundleName) const
186 {
187 std::shared_ptr<NotificationAppPrivileges> appPrivileges = GetAppPrivileges(bundleName);
188 if (appPrivileges == nullptr) {
189 return false;
190 }
191 return appPrivileges->IsReminderEnabled();
192 }
193
IsBannerEnabled(const std::string bundleName) const194 bool NotificationConfigParse::IsBannerEnabled(const std::string bundleName) const
195 {
196 std::shared_ptr<NotificationAppPrivileges> appPrivileges = GetAppPrivileges(bundleName);
197 if (appPrivileges != nullptr && appPrivileges->IsBannerEnabled()) {
198 return true;
199 }
200 #ifdef ENABLE_ANS_ADDITIONAL_CONTROL
201 int32_t ctrlResult = EXTENTION_WRAPPER->BannerControl(bundleName);
202 return (ctrlResult == ERR_OK) ? true : false;
203 #else
204 return false;
205 #endif
206 }
207
GetFlowCtrlConfigFromCCM(FlowControlThreshold & threshold)208 void NotificationConfigParse::GetFlowCtrlConfigFromCCM(FlowControlThreshold &threshold)
209 {
210 nlohmann::json root;
211 std::string JsonPoint = "/";
212 JsonPoint.append(CFG_KEY_NOTIFICATION_SERVICE);
213 if (!GetConfigJson(JsonPoint, root)) {
214 ANS_LOGE("Failed to get JsonPoint CCM config file");
215 return;
216 }
217 if (!root.contains(CFG_KEY_NOTIFICATION_SERVICE)) {
218 ANS_LOGW("GetFlowCtrlConfigFromCCM not found jsonKey");
219 return;
220 }
221 nlohmann::json affects = root[CFG_KEY_NOTIFICATION_SERVICE];
222 if (affects.is_null() || affects.empty()) {
223 ANS_LOGE("GetFlowCtrlConfigFromCCM failed as invalid ccmFlowCtrlConfig json");
224 return;
225 }
226 if (affects.contains(CFG_KEY_MAX_CREATE_NUM_PERSECOND)) {
227 threshold.maxCreateNumPerSecond = affects[CFG_KEY_MAX_CREATE_NUM_PERSECOND];
228 }
229
230 if (affects.contains(CFG_KEY_MAX_UPDATE_NUM_PERSECOND)) {
231 threshold.maxUpdateNumPerSecond = affects[CFG_KEY_MAX_UPDATE_NUM_PERSECOND];
232 }
233
234 if (affects.contains(CFG_KEY_MAX_CREATE_NUM_PERSECOND_PERAPP)) {
235 threshold.maxCreateNumPerSecondPerApp = affects[CFG_KEY_MAX_CREATE_NUM_PERSECOND_PERAPP];
236 }
237
238 if (affects.contains(CFG_KEY_MAX_UPDATE_NUM_PERSECOND_PERAPP)) {
239 threshold.maxUpdateNumPerSecondPerApp = affects[CFG_KEY_MAX_UPDATE_NUM_PERSECOND_PERAPP];
240 }
241
242 ANS_LOGI("GetFlowCtrlConfigFromCCM success");
243 }
244
GetSmartReminderEnableList(std::vector<std::string> & deviceTypes)245 bool NotificationConfigParse::GetSmartReminderEnableList(std::vector<std::string>& deviceTypes)
246 {
247 nlohmann::json root;
248 std::string jsonPoint = "/";
249 jsonPoint.append(CFG_KEY_NOTIFICATION_SERVICE);
250 jsonPoint.append("/");
251 jsonPoint.append(CFG_KEY_SMART_REMINDER_ENABLE_LIST);
252 if (!GetConfigJson(jsonPoint, root)) {
253 ANS_LOGE("get configJson fail");
254 return false;
255 }
256
257 if (root.find(CFG_KEY_NOTIFICATION_SERVICE) == root.end()) {
258 ANS_LOGE("find notificationService fail");
259 return false;
260 }
261
262 nlohmann::json smartReminderEnableList = root[CFG_KEY_NOTIFICATION_SERVICE][CFG_KEY_SMART_REMINDER_ENABLE_LIST];
263 if (smartReminderEnableList.is_null() || !smartReminderEnableList.is_array() || smartReminderEnableList.empty()) {
264 ANS_LOGE("smartReminderEnableList is invalid");
265 return false;
266 }
267 std::lock_guard<std::mutex> lock(mutex_);
268 deviceTypes = smartReminderEnableList.get<std::vector<std::string>>();
269 return true;
270 }
271
GetMirrorNotificationEnabledStatus(std::vector<std::string> & deviceTypes)272 bool NotificationConfigParse::GetMirrorNotificationEnabledStatus(std::vector<std::string>& deviceTypes)
273 {
274 nlohmann::json root;
275 std::string jsonPoint = "/";
276 jsonPoint.append(CFG_KEY_NOTIFICATION_SERVICE);
277 jsonPoint.append("/");
278 jsonPoint.append(CFG_KEY_MIRROR_NOTIFICAITON_ENABLED_STATUS);
279 if (!GetConfigJson(jsonPoint, root)) {
280 ANS_LOGE("get configJson fail");
281 return false;
282 }
283
284 if (root.find(CFG_KEY_NOTIFICATION_SERVICE) == root.end()) {
285 ANS_LOGE("find notificationService fail");
286 return false;
287 }
288
289 nlohmann::json mirrorNotificationEnabledStatus =
290 root[CFG_KEY_NOTIFICATION_SERVICE][CFG_KEY_MIRROR_NOTIFICAITON_ENABLED_STATUS];
291 if (mirrorNotificationEnabledStatus.is_null() || !mirrorNotificationEnabledStatus.is_array() ||
292 mirrorNotificationEnabledStatus.empty()) {
293 ANS_LOGE("mirrorNotificationEnabledStatus is invalid");
294 return false;
295 }
296 std::lock_guard<std::mutex> lock(mutex_);
297 deviceTypes = mirrorNotificationEnabledStatus.get<std::vector<std::string>>();
298 return true;
299 }
300
GetAppAndDeviceRelationMap(std::map<std::string,std::string> & relationMap)301 bool NotificationConfigParse::GetAppAndDeviceRelationMap(std::map<std::string, std::string>& relationMap)
302 {
303 nlohmann::json root;
304 std::string jsonPoint = "/";
305 jsonPoint.append(CFG_KEY_NOTIFICATION_SERVICE);
306 jsonPoint.append("/");
307 jsonPoint.append(CFG_KEY_APP_AND_DEVICE_RELATION_MAP);
308 if (!GetConfigJson(jsonPoint, root)) {
309 ANS_LOGE("get configJson fail");
310 return false;
311 }
312
313 if (root.find(CFG_KEY_NOTIFICATION_SERVICE) == root.end()) {
314 ANS_LOGE("find notificationService fail");
315 return false;
316 }
317
318 nlohmann::json appAndDeviceRelationMap = root[CFG_KEY_NOTIFICATION_SERVICE][CFG_KEY_APP_AND_DEVICE_RELATION_MAP];
319 if (appAndDeviceRelationMap.is_null() || appAndDeviceRelationMap.empty()) {
320 ANS_LOGE("appAndDeviceRelationMap is invalid");
321 return false;
322 }
323 std::lock_guard<std::mutex> lock(mutex_);
324 for (auto& appAndDeviceRelation : appAndDeviceRelationMap.items()) {
325 relationMap[appAndDeviceRelation.key()] = appAndDeviceRelation.value();
326 }
327 return true;
328 }
329
GetCollaborativeDeleteType() const330 std::unordered_set<std::string> NotificationConfigParse::GetCollaborativeDeleteType() const
331 {
332 nlohmann::json root;
333 std::string JsonPoint = "/";
334 JsonPoint.append(CFG_KEY_NOTIFICATION_SERVICE);
335 JsonPoint.append("/");
336 JsonPoint.append(CFG_KEY_COLLABORATIVE_DELETE_TYPES);
337 if (!GetConfigJson(JsonPoint, root)) {
338 ANS_LOGE("GetConfigJson faild");
339 return std::unordered_set<std::string>();
340 }
341 if (root.find(CFG_KEY_NOTIFICATION_SERVICE) == root.end()) {
342 ANS_LOGE("appPrivileges null");
343 return std::unordered_set<std::string>();
344 }
345
346 nlohmann::json collaborativeDeleteTypes = root[CFG_KEY_NOTIFICATION_SERVICE][CFG_KEY_COLLABORATIVE_DELETE_TYPES];
347 if (collaborativeDeleteTypes.empty() && !collaborativeDeleteTypes.is_array()) {
348 ANS_LOGE("collaborativeDeleteTypes null or no array");
349 return std::unordered_set<std::string>();
350 }
351 std::unordered_set<std::string> collaborativeDeleteTypeSet;
352 for (const auto &item : collaborativeDeleteTypes) {
353 if (item.is_string()) {
354 collaborativeDeleteTypeSet.insert(item.get<std::string>());
355 }
356 }
357
358 return collaborativeDeleteTypeSet;
359 }
360
GetFilterUidAndBundleName(const std::string & key)361 bool NotificationConfigParse::GetFilterUidAndBundleName(const std::string &key)
362 {
363 nlohmann::json root;
364 std::string jsonPoint = "/";
365 jsonPoint.append(CFG_KEY_NOTIFICATION_SERVICE).append("/").append(COLLABORATION_FILTER).append("/").append(key);
366 if (!GetConfigJson(jsonPoint, root)) {
367 ANS_LOGE("Failed to get jsonPoint CCM config file.");
368 return false;
369 }
370
371 if (!root.contains(CFG_KEY_NOTIFICATION_SERVICE) ||
372 !root[CFG_KEY_NOTIFICATION_SERVICE].contains(COLLABORATION_FILTER)) {
373 ANS_LOGE("Not found jsonKey collaborationFilter.");
374 return false;
375 }
376
377 nlohmann::json collaborationFilter = root[CFG_KEY_NOTIFICATION_SERVICE][COLLABORATION_FILTER];
378 if (collaborationFilter.is_null() || collaborationFilter.empty()) {
379 ANS_LOGE("GetCollaborationFilter failed as invalid ccmCollaborationFilter json.");
380 return false;
381 }
382 if (collaborationFilter.contains(key) && collaborationFilter[key].is_array()) {
383 for (const auto& item : collaborationFilter[key]) {
384 if (item.is_number_integer()) {
385 uidList_.push_back(item.get<int32_t>());
386 }
387 if (item.is_string()) {
388 bundleNameList_.push_back(item.get<std::string>());
389 }
390 }
391 return true;
392 }
393 return false;
394 }
395
GetCollaborationFilter()396 void NotificationConfigParse::GetCollaborationFilter()
397 {
398 if (!GetFilterUidAndBundleName(COLLABORATION_FILTER_KEY_UID)) {
399 ANS_LOGW("Failed to get filterUid.");
400 }
401 if (!GetFilterUidAndBundleName(COLLABORATION_FILTER_KEY_NAME)) {
402 ANS_LOGW("Failed to get filterBundleName.");
403 }
404 }
405
IsInCollaborationFilter(const std::string & bundleName,int32_t uid) const406 bool NotificationConfigParse::IsInCollaborationFilter(const std::string& bundleName, int32_t uid) const
407 {
408 if (uidList_.empty() && bundleNameList_.empty()) {
409 ANS_LOGW("UidList and bundleNameList empty.");
410 return false;
411 }
412
413 if (std::find(uidList_.begin(), uidList_.end(), uid) != uidList_.end()) {
414 ANS_LOGI("Uid <%{public}d> in CollaborationFilter.", uid);
415 return true;
416 }
417
418 if (std::find(bundleNameList_.begin(), bundleNameList_.end(), bundleName) != bundleNameList_.end()) {
419 ANS_LOGI("BundleName <%{public}s> in CollaborationFilter.", bundleName.c_str());
420 return true;
421 }
422
423 ANS_LOGI("Uid <%{public}d> and BundleName <%{public}s> not in CollaborationFilter.", uid, bundleName.c_str());
424 return false;
425 }
426
GetStartAbilityTimeout()427 uint32_t NotificationConfigParse::GetStartAbilityTimeout()
428 {
429 nlohmann::json root;
430 std::string JsonPoint = "/";
431 JsonPoint.append(CFG_KEY_NOTIFICATION_SERVICE);
432 if (!GetConfigJson(JsonPoint, root)) {
433 ANS_LOGE("Failed to get JsonPoint CCM config file");
434 return 0;
435 }
436 if (!root.contains(CFG_KEY_NOTIFICATION_SERVICE)) {
437 ANS_LOGW("GetStartAbilityTimeout not found jsonKey");
438 return 0;
439 }
440 nlohmann::json affects = root[CFG_KEY_NOTIFICATION_SERVICE];
441 if (affects.is_null() || affects.empty()) {
442 ANS_LOGE("GetStartAbilityTimeout failed as invalid ccmFlowCtrlConfig json");
443 return 0;
444 }
445 if (affects.contains(CFG_KEY_START_ABILITY_TIMEOUT)) {
446 return affects[CFG_KEY_START_ABILITY_TIMEOUT];
447 }
448
449 return 0;
450 }
451
GetReportTrustListConfig()452 void NotificationConfigParse::GetReportTrustListConfig()
453 {
454 nlohmann::json root;
455 std::string reportJsonPoint = "/";
456 reportJsonPoint.append(CFG_KEY_NOTIFICATION_SERVICE);
457 reportJsonPoint.append("/");
458 reportJsonPoint.append(CFG_KEY_DFX_NORMAL_EVENT);
459 if (!GetConfigJson(reportJsonPoint, root)) {
460 return;
461 }
462 if (root.find(CFG_KEY_NOTIFICATION_SERVICE) == root.end()) {
463 ANS_LOGE("Failed to get JsonPoint CCM config file");
464 return;
465 }
466
467 nlohmann::json reportTrustList = root[CFG_KEY_NOTIFICATION_SERVICE][CFG_KEY_DFX_NORMAL_EVENT];
468 if (reportTrustList.is_null() || reportTrustList.empty() || !reportTrustList.is_array()) {
469 ANS_LOGE("GetReportTrustListConfig failed as invalid dfx_normal_events json.");
470 return;
471 }
472 for (auto &reportTrust : reportTrustList) {
473 reporteTrustSet_.emplace(reportTrust);
474 }
475 return;
476 }
477
478
IsReportTrustList(const std::string & bundleName) const479 bool NotificationConfigParse::IsReportTrustList(const std::string& bundleName) const
480 {
481 return reporteTrustSet_.count(bundleName);
482 }
483
484 } // namespace Notification
485 } // namespace OHOS
486