1 /*
2 * Copyright (c) 2024-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 #ifdef NOTIFICATION_SMART_REMINDER_SUPPORTED
17 #include "smart_reminder_center.h"
18
19 #include "ans_log_wrapper.h"
20 #include "ipc_skeleton.h"
21 #include "notification_bundle_option.h"
22 #include "notification_config_parse.h"
23 #include "notification_local_live_view_content.h"
24 #include "notification_preferences.h"
25 #include "os_account_manager.h"
26 #include "screenlock_manager.h"
27 #include "string_utils.h"
28 #include "distributed_device_data_service.h"
29 #include "bundle_manager_helper.h"
30 #include "int_wrapper.h"
31 #include "string_wrapper.h"
32 #ifdef ENABLE_ANS_PRIVILEGED_MESSAGE_EXT_WRAPPER
33 #include "notification_extension_wrapper.h"
34 #endif
35 #include "os_account_manager_helper.h"
36 #include "distributed_data_define.h"
37
38 namespace OHOS {
39 namespace Notification {
40 using namespace std;
41 constexpr int32_t CONTROL_BY_SMART_REMINDER = 1 << 15;
42
SmartReminderCenter()43 SmartReminderCenter::SmartReminderCenter()
44 {
45 DelayedSingleton<NotificationConfigParse>::GetInstance()->GetCollaborationFilter();
46 if (!DelayedSingleton<NotificationConfigParse>::GetInstance()->GetCurrentSlotReminder(currentReminderMethods_)) {
47 return;
48 }
49 GetMultiDeviceReminder();
50 }
51
GetMultiDeviceReminder()52 void SmartReminderCenter::GetMultiDeviceReminder()
53 {
54 nlohmann::json root;
55 string multiJsonPoint = "/";
56 multiJsonPoint.append(NotificationConfigParse::CFG_KEY_NOTIFICATION_SERVICE);
57 multiJsonPoint.append("/");
58 multiJsonPoint.append(MULTI_DEVICE_REMINDER);
59 if (!DelayedSingleton<NotificationConfigParse>::GetInstance()->GetConfigJson(multiJsonPoint, root)) {
60 ANS_LOGE("Failed to get multiDeviceReminder CCM config file.");
61 return;
62 }
63
64 if (root.find(NotificationConfigParse::CFG_KEY_NOTIFICATION_SERVICE) == root.end()) {
65 ANS_LOGE("GetMultiDeviceReminder failed as can not find notificationService.");
66 return;
67 }
68
69 nlohmann::json multiDeviceRemindJson =
70 root[NotificationConfigParse::CFG_KEY_NOTIFICATION_SERVICE][MULTI_DEVICE_REMINDER];
71 if (multiDeviceRemindJson.is_null() || !multiDeviceRemindJson.is_array() || multiDeviceRemindJson.empty()) {
72 ANS_LOGE("GetMultiDeviceReminder failed as invalid multiDeviceReminder json.");
73 return;
74 }
75
76 reminderMethods_.clear();
77 for (auto &singleDeviceRemindJson : multiDeviceRemindJson) {
78 if (singleDeviceRemindJson.is_null() || !singleDeviceRemindJson.is_object()) {
79 continue;
80 }
81
82 if (singleDeviceRemindJson.find(ReminderAffected::DEVICE_TYPE) == singleDeviceRemindJson.end() ||
83 singleDeviceRemindJson[ReminderAffected::DEVICE_TYPE].is_null() ||
84 !singleDeviceRemindJson[ReminderAffected::DEVICE_TYPE].is_string()) {
85 continue;
86 }
87
88 if (singleDeviceRemindJson.find(REMINDER_FILTER_DEVICE) == singleDeviceRemindJson.end() ||
89 singleDeviceRemindJson[REMINDER_FILTER_DEVICE].is_null() ||
90 !singleDeviceRemindJson[REMINDER_FILTER_DEVICE].is_array() ||
91 singleDeviceRemindJson[REMINDER_FILTER_DEVICE].empty()) {
92 continue;
93 }
94 ParseReminderFilterDevice(singleDeviceRemindJson[REMINDER_FILTER_DEVICE],
95 singleDeviceRemindJson[ReminderAffected::DEVICE_TYPE].get<string>());
96 }
97
98 if (reminderMethods_.size() <= 0) {
99 ANS_LOGW("GetMultiDeviceReminder failed as Invalid reminderMethods size.");
100 }
101 }
102
ParseReminderFilterDevice(const nlohmann::json & root,const string & deviceType)103 void SmartReminderCenter::ParseReminderFilterDevice(const nlohmann::json &root, const string &deviceType)
104 {
105 map<string, vector<shared_ptr<ReminderAffected>>> reminderFilterDevice;
106 for (auto &reminderFilterDeviceJson : root) {
107 NotificationConstant::SlotType slotType;
108 if (reminderFilterDeviceJson.find(SLOT_TYPE) == reminderFilterDeviceJson.end() ||
109 reminderFilterDeviceJson[SLOT_TYPE].is_null() ||
110 !reminderFilterDeviceJson[SLOT_TYPE].is_string()) {
111 continue;
112 }
113
114 if (reminderFilterDeviceJson.find(REMINDER_FILTER_SLOT) == reminderFilterDeviceJson.end() ||
115 reminderFilterDeviceJson[REMINDER_FILTER_SLOT].is_null() ||
116 !reminderFilterDeviceJson[REMINDER_FILTER_SLOT].is_array() ||
117 reminderFilterDeviceJson[REMINDER_FILTER_SLOT].empty()) {
118 continue;
119 }
120
121 std::string slotTypes = reminderFilterDeviceJson[SLOT_TYPE].get<std::string>();
122 std::vector<std::string> slotTypeVector;
123 StringUtils::Split(slotTypes, SPLIT_FLAG, slotTypeVector);
124
125 for (std::string slotTypeStr : slotTypeVector) {
126 if (!NotificationSlot::GetSlotTypeByString(slotTypeStr, slotType)) {
127 continue;
128 }
129 ParseReminderFilterSlot(reminderFilterDeviceJson[REMINDER_FILTER_SLOT],
130 to_string(static_cast<int32_t>(slotType)), reminderFilterDevice);
131 }
132 }
133 if (reminderFilterDevice.size() > 0) {
134 reminderMethods_[deviceType] = move(reminderFilterDevice);
135 } else {
136 ANS_LOGI("ParseReminderFilterDevice failed as Invalid reminderFilterDevice size. deviceType = %{public}s.",
137 deviceType.c_str());
138 }
139 }
140
ParseReminderFilterSlot(const nlohmann::json & root,const string & notificationType,map<string,vector<shared_ptr<ReminderAffected>>> & reminderFilterDevice) const141 void SmartReminderCenter::ParseReminderFilterSlot(
142 const nlohmann::json &root,
143 const string ¬ificationType,
144 map<string, vector<shared_ptr<ReminderAffected>>> &reminderFilterDevice) const
145 {
146 vector<shared_ptr<ReminderAffected>> reminderFilterSlot;
147 for (auto &reminderFilterSlotJson : root) {
148 NotificationContent::Type contentType;
149 bool validContentType = true;
150
151 if (reminderFilterSlotJson.find(CONTENT_TYPE) == reminderFilterSlotJson.end() ||
152 reminderFilterSlotJson[CONTENT_TYPE].is_null() ||
153 !reminderFilterSlotJson[CONTENT_TYPE].is_string() ||
154 !NotificationContent::GetContentTypeByString(
155 reminderFilterSlotJson[CONTENT_TYPE].get<std::string>(), contentType)) {
156 validContentType = false;
157 }
158
159 if (reminderFilterSlotJson.find(REMINDER_FILTER_CONTENT) == reminderFilterSlotJson.end() ||
160 reminderFilterSlotJson[REMINDER_FILTER_CONTENT].is_null() ||
161 !reminderFilterSlotJson[REMINDER_FILTER_CONTENT].is_array() ||
162 reminderFilterSlotJson[REMINDER_FILTER_CONTENT].empty()) {
163 validContentType = false;
164 }
165
166 if (validContentType) {
167 string localNotificationType = notificationType;
168 localNotificationType.append("#");
169 localNotificationType.append(to_string(static_cast<int32_t>(contentType)));
170 ParseReminderFilterContent(
171 reminderFilterSlotJson[REMINDER_FILTER_CONTENT], localNotificationType, reminderFilterDevice);
172 continue;
173 }
174 shared_ptr<ReminderAffected> reminderAffected = make_shared<ReminderAffected>();
175 if (reminderAffected->FromJson(reminderFilterSlotJson)) {
176 reminderFilterSlot.push_back(reminderAffected);
177 }
178 }
179 if (reminderFilterSlot.size() > 0) {
180 reminderFilterDevice[notificationType] = move(reminderFilterSlot);
181 }
182 }
183
ParseReminderFilterContent(const nlohmann::json & root,const string & notificationType,map<string,vector<shared_ptr<ReminderAffected>>> & reminderFilterDevice) const184 void SmartReminderCenter::ParseReminderFilterContent(
185 const nlohmann::json &root,
186 const string ¬ificationType,
187 map<string, vector<shared_ptr<ReminderAffected>>> &reminderFilterDevice) const
188 {
189 vector<shared_ptr<ReminderAffected>> reminderFilterContent;
190 for (auto &reminderFilterContentJson : root) {
191 bool validTypeCode = true;
192 if (reminderFilterContentJson.find(TYPE_CODE) == reminderFilterContentJson.end() ||
193 reminderFilterContentJson[TYPE_CODE].is_null() ||
194 !reminderFilterContentJson[TYPE_CODE].is_number()) {
195 validTypeCode = false;
196 }
197
198 if (reminderFilterContentJson.find(REMINDER_FILTER_CODE) == reminderFilterContentJson.end() ||
199 reminderFilterContentJson[REMINDER_FILTER_CODE].is_null() ||
200 !reminderFilterContentJson[REMINDER_FILTER_CODE].is_array() ||
201 reminderFilterContentJson[REMINDER_FILTER_CODE].empty()) {
202 validTypeCode = false;
203 }
204
205 if (validTypeCode) {
206 int32_t typeCode = reminderFilterContentJson[TYPE_CODE].get<int32_t>();
207 string localNotificationType = notificationType;
208 localNotificationType.append("#");
209 localNotificationType.append(to_string(typeCode));
210 ParseReminderFilterCode(
211 reminderFilterContentJson[REMINDER_FILTER_CODE], localNotificationType, reminderFilterDevice);
212 continue;
213 }
214 shared_ptr<ReminderAffected> reminderAffected = make_shared<ReminderAffected>();
215 if (reminderAffected->FromJson(reminderFilterContentJson)) {
216 reminderFilterContent.push_back(reminderAffected);
217 }
218 }
219 if (reminderFilterContent.size() > 0) {
220 reminderFilterDevice[notificationType] = move(reminderFilterContent);
221 }
222 }
223
ParseReminderFilterCode(const nlohmann::json & root,const string & notificationType,map<string,vector<shared_ptr<ReminderAffected>>> & reminderFilterDevice) const224 void SmartReminderCenter::ParseReminderFilterCode(
225 const nlohmann::json &root,
226 const string ¬ificationType,
227 map<string, vector<shared_ptr<ReminderAffected>>> &reminderFilterDevice) const
228 {
229 vector<shared_ptr<ReminderAffected>> reminderFilterCode;
230 for (auto &reminderFilterCodeJson : root) {
231 shared_ptr<ReminderAffected> reminderAffected = make_shared<ReminderAffected>();
232 if (reminderAffected->FromJson(reminderFilterCodeJson)) {
233 reminderFilterCode.push_back(reminderAffected);
234 }
235 }
236 if (reminderFilterCode.size() > 0) {
237 reminderFilterDevice[notificationType] = move(reminderFilterCode);
238 }
239 }
240
IsCollaborationAllowed(const sptr<NotificationRequest> & request) const241 bool SmartReminderCenter::IsCollaborationAllowed(const sptr<NotificationRequest>& request) const
242 {
243 if (!request->IsSystemApp()) {
244 ANS_LOGI("IsSystemApp <%{public}d> allowed to collaborate.", request->IsSystemApp());
245 return true;
246 }
247 if (request->IsNotDistributed()) {
248 ANS_LOGI("IsNotDistributed <%{public}d> not allowed to collaborate", request->IsNotDistributed());
249 return false;
250 }
251 if (request->IsForceDistributed()) {
252 ANS_LOGI("IsForceDistributed <%{public}d> allowed to collaborate", request->IsForceDistributed());
253 return true;
254 }
255 return !DelayedSingleton<NotificationConfigParse>::GetInstance()->IsInCollaborationFilter(
256 request->GetOwnerBundleName(), request->GetCreatorUid());
257 }
258
ReminderDecisionProcess(const sptr<NotificationRequest> & request) const259 void SmartReminderCenter::ReminderDecisionProcess(const sptr<NotificationRequest> &request) const
260 {
261 shared_ptr<map<string, shared_ptr<NotificationFlags>>> notificationFlagsOfDevices =
262 make_shared<map<string, shared_ptr<NotificationFlags>>>();
263 shared_ptr<NotificationFlags> defaultFlag = make_shared<NotificationFlags>();
264 NotificationConstant::SlotType slotType = request->GetSlotType();
265
266 #ifdef ENABLE_ANS_PRIVILEGED_MESSAGE_EXT_WRAPPER
267 if (EXTENTION_WRAPPER->IsPrivilegeMessage(request)) {
268 ANS_LOGD("Privilege message handle ReminderDecisionProcess.");
269 (*notificationFlagsOfDevices)[NotificationConstant::CURRENT_DEVICE_TYPE] = request->GetFlags();
270 request->SetDeviceFlags(notificationFlagsOfDevices);
271 return;
272 }
273 #endif
274
275 auto iter = currentReminderMethods_.find(slotType);
276 if (iter != currentReminderMethods_.end()) {
277 // Only config file can set reminder open now. Otherwise, change iter->second to 11111
278 auto flag = std::make_shared<NotificationFlags>(iter->second->GetReminderFlags());
279 (*notificationFlagsOfDevices)[NotificationConstant::CURRENT_DEVICE_TYPE] = flag;
280 defaultFlag = iter->second;
281 }
282 if (!IsCollaborationAllowed(request)) {
283 request->SetDeviceFlags(notificationFlagsOfDevices);
284 return;
285 }
286
287 set<string> syncDevices;
288 set<string> smartDevices;
289 map<string, bitset<DistributedDeviceStatus::STATUS_SIZE>> statusMap;
290 InitValidDevices(syncDevices, smartDevices, statusMap, request);
291 if (syncDevices.size() <= 1) {
292 request->SetDeviceFlags(notificationFlagsOfDevices);
293 return;
294 }
295
296 for (auto &reminderMethod : reminderMethods_) {
297 HandleReminderMethods(
298 reminderMethod.first, reminderMethod.second, request,
299 syncDevices, smartDevices, defaultFlag, statusMap,
300 notificationFlagsOfDevices);
301 }
302 request->SetDeviceFlags(notificationFlagsOfDevices);
303 }
304
InitValidDevices(set<string> & syncDevices,set<string> & smartDevices,map<string,bitset<DistributedDeviceStatus::STATUS_SIZE>> & statusMap,const sptr<NotificationRequest> & request) const305 void SmartReminderCenter::InitValidDevices(
306 set<string> &syncDevices, set<string> &smartDevices,
307 map<string, bitset<DistributedDeviceStatus::STATUS_SIZE>> &statusMap,
308 const sptr<NotificationRequest> &request) const
309 {
310 auto notificationControlFlags = request->GetNotificationControlFlags();
311 syncDevices.insert(NotificationConstant::CURRENT_DEVICE_TYPE);
312 smartDevices.insert(NotificationConstant::CURRENT_DEVICE_TYPE);
313 bitset<DistributedDeviceStatus::STATUS_SIZE> status;
314 GetDeviceStatusByType(NotificationConstant::CURRENT_DEVICE_TYPE, status);
315 statusMap.insert(
316 pair<string, bitset<DistributedDeviceStatus::STATUS_SIZE>>(NotificationConstant::CURRENT_DEVICE_TYPE, status));
317
318 for (std::string deviceType : NotificationConstant::DEVICESTYPES) {
319 bool affordConsume = false;
320 NotificationSubscriberManager::GetInstance()->IsDeviceTypeAffordConsume(deviceType, request, affordConsume);
321 if (!affordConsume) {
322 ANS_LOGI("deviceType = %{public}s", deviceType.c_str());
323 continue;
324 }
325
326 if (NotificationConstant::PC_DEVICE_TYPE == deviceType || NotificationConstant::PAD_DEVICE_TYPE == deviceType) {
327 #ifdef ALL_SCENARIO_COLLABORATION
328 InitPcPadDevices(deviceType, syncDevices, smartDevices, statusMap, request);
329 #endif
330 continue;
331 }
332
333 GetDeviceStatusByType(deviceType, status);
334 statusMap.insert(pair<string, bitset<DistributedDeviceStatus::STATUS_SIZE>>(deviceType, status));
335 request->AdddeviceStatu(deviceType, status.bitset<DistributedDeviceStatus::STATUS_SIZE>::to_string());
336
337 if (NotificationConstant::SlotType::LIVE_VIEW == request->GetSlotType()) {
338 bool isEnable = false;
339 std::string queryDeviceType = deviceType;
340 if (deviceType.compare(NotificationConstant::WEARABLE_DEVICE_TYPE) == 0) {
341 queryDeviceType = NotificationConstant::LITEWEARABLE_DEVICE_TYPE;
342 }
343 NotificationPreferences::GetInstance()->IsDistributedEnabledBySlot(
344 request->GetSlotType(), queryDeviceType, isEnable);
345 if (!isEnable) {
346 ANS_LOGI("liveView smart switch is closed, deviceType = %{public}s", deviceType.c_str());
347 continue;
348 }
349 syncDevices.insert(deviceType);
350 smartDevices.insert(deviceType);
351 request->SetNotificationControlFlags(notificationControlFlags | CONTROL_BY_SMART_REMINDER);
352 } else {
353 if (NotificationConstant::SlotType::SOCIAL_COMMUNICATION != request->GetSlotType() &&
354 NotificationConstant::SlotType::SERVICE_REMINDER != request->GetSlotType() &&
355 NotificationConstant::SlotType::CUSTOMER_SERVICE != request->GetSlotType()) {
356 ANS_LOGI("unaffect slot");
357 continue;
358 }
359 bool distributedSwitch = GetDistributedSwitch(deviceType);
360 if (!distributedSwitch) {
361 ANS_LOGI("distributed switch is closed, deveiceType = %{public}s", deviceType.c_str());
362 continue;
363 }
364 bool appSwitch = GetAppSwitch(deviceType, request->GetOwnerBundleName(), request->GetOwnerUid());
365 // app-close
366 if (!appSwitch) {
367 ANS_LOGI("app switch is closed, deveiceType = %{public}s", deviceType.c_str());
368 continue;
369 }
370
371 bool smartSwitch = GetSmartSwitch(deviceType);
372 ANS_LOGI("smart switch deviceType = %{public}s status = %{public}d", deviceType.c_str(), smartSwitch);
373 // app-open ,smart-open
374 if (smartSwitch) {
375 syncDevices.insert(deviceType);
376 smartDevices.insert(deviceType);
377 request->SetNotificationControlFlags(notificationControlFlags | CONTROL_BY_SMART_REMINDER);
378 continue;
379 }
380 // app-open, smart-close
381 syncDevices.insert(deviceType);
382 }
383 }
384 string syncDevicesStr;
385 string smartDevicesStr;
386 for (auto it = syncDevices.begin(); it != syncDevices.end(); ++it) {
387 syncDevicesStr = syncDevicesStr + *it + StringUtils::SPLIT_CHAR;
388 }
389 for (auto it = smartDevices.begin(); it != smartDevices.end(); ++it) {
390 smartDevicesStr = smartDevicesStr + *it + StringUtils::SPLIT_CHAR;
391 }
392 ANS_LOGI("sync device: %{public}s", syncDevicesStr.c_str());
393 ANS_LOGI("smart device: %{public}s", smartDevicesStr.c_str());
394 return;
395 }
396
397 #ifdef ALL_SCENARIO_COLLABORATION
InitPcPadDevices(const string & deviceType,set<string> & syncDevices,set<string> & smartDevices,map<string,bitset<DistributedDeviceStatus::STATUS_SIZE>> & statusMap,const sptr<NotificationRequest> & request) const398 void SmartReminderCenter::InitPcPadDevices(const string &deviceType,
399 set<string> &syncDevices, set<string> &smartDevices,
400 map<string, bitset<DistributedDeviceStatus::STATUS_SIZE>> &statusMap,
401 const sptr<NotificationRequest> &request) const
402 {
403 if (request->GetOwnerBundleName().empty()) {
404 ANS_LOGI("PC/PAD init, bundleName null");
405 return;
406 }
407 if (request->GetClassification() == NotificationConstant::ANS_VOIP) {
408 ANS_LOGI("PC/PAD init, pc/pad not support voip");
409 return;
410 }
411 if (NotificationConstant::SlotType::LIVE_VIEW == request->GetSlotType() &&
412 NotificationConstant::PC_DEVICE_TYPE == deviceType) {
413 ANS_LOGI("PC/PAD init, pc not support liveView");
414 return;
415 }
416 // used device
417 DeviceStatus deviceStatus = DelayedSingleton<DistributedDeviceStatus>::GetInstance()->
418 GetMultiDeviceStatus(deviceType, STATUS_UNLOCKED_USED_FLAG);
419 if (deviceStatus.deviceType.empty()) {
420 ANS_LOGI("PC/PAD init, not get any used device, type = %{public}s", deviceType.c_str());
421 return;
422 }
423 // switch
424 string deviceId = deviceStatus.deviceId;
425 if (NotificationConstant::SlotType::LIVE_VIEW == request->GetSlotType()) {
426 if (!DistributedDeviceDataService::GetInstance().GetDeviceLiveViewEnable(deviceType, deviceId)) {
427 ANS_LOGI("PC/PAD init, liveView switch is closed , type = %{public}s", deviceType.c_str());
428 return;
429 }
430 } else {
431 if (!DistributedDeviceDataService::GetInstance().GetDeviceNotificationEnable(deviceType, deviceId)) {
432 ANS_LOGI("PC/PAD init, notification switch is closed , type = %{public}s", deviceType.c_str());
433 return;
434 }
435 }
436
437 std::string bundleName = request->GetOwnerBundleName();
438 int32_t userId = request->GetOwnerUserId();
439 AppExecFwk::BundleInfo bundleInfo;
440 AppExecFwk::ApplicationInfo appInfo;
441 AppExecFwk::BundleResourceInfo bundleResourceInfo;
442 std::shared_ptr<BundleManagerHelper> bundleManager = BundleManagerHelper::GetInstance();
443 if (bundleManager != nullptr) {
444 // system app
445 if (bundleManager->CheckSystemApp(bundleName, userId)) {
446 ANS_LOGI("PC/PAD init, application is systemApp, type = %{public}s, bundleName = %{public}s",
447 deviceType.c_str(), bundleName.c_str());
448 return;
449 }
450 int32_t flags = static_cast<int32_t>(AppExecFwk::GetBundleInfoFlag::GET_BUNDLE_INFO_WITH_APPLICATION);
451 if (!bundleManager->GetBundleInfoV9(bundleName, flags, bundleInfo, userId)) {
452 ANS_LOGE("PC/PAD init, GetApplicationInfo error, type = %{public}s, bundleName = %{public}s",
453 deviceType.c_str(), bundleName.c_str());
454 return;
455 }
456 appInfo = bundleInfo.applicationInfo;
457 if (bundleManager->GetBundleResourceInfo(bundleName, bundleResourceInfo, appInfo.appIndex) != ERR_OK) {
458 ANS_LOGE("PC/PAD init, GetBundleResourceInfo error, type = %{public}s, bundleName = %{public}s",
459 deviceType.c_str(), bundleName.c_str());
460 return;
461 }
462 // installed bundle
463 if (DistributedDeviceDataService::GetInstance().CheckDeviceBundleExist(
464 deviceType, deviceId, bundleName, bundleResourceInfo.label)) {
465 ANS_LOGI("PC/PAD init, application has installed, type = %{public}s, bundleName = %{public}s",
466 deviceType.c_str(), bundleName.c_str());
467 return;
468 }
469 } else {
470 ANS_LOGE("get bundleManager fail");
471 return;
472 }
473 FillRequestExtendInfo(deviceType, deviceStatus, request, appInfo, bundleResourceInfo);
474 statusMap.insert(pair<string, bitset<DistributedDeviceStatus::STATUS_SIZE>>(
475 deviceType, bitset<DistributedDeviceStatus::STATUS_SIZE>(deviceStatus.status)));
476 syncDevices.insert(deviceType);
477 smartDevices.insert(deviceType);
478 return;
479 }
480 #endif
481
FillRequestExtendInfo(const string & deviceType,DeviceStatus & deviceStatus,const sptr<NotificationRequest> & request,const AppExecFwk::ApplicationInfo & appInfo,const AppExecFwk::BundleResourceInfo & bundleResourceInfo) const482 void SmartReminderCenter::FillRequestExtendInfo(const string &deviceType, DeviceStatus &deviceStatus,
483 const sptr<NotificationRequest> &request,
484 const AppExecFwk::ApplicationInfo &appInfo,
485 const AppExecFwk::BundleResourceInfo &bundleResourceInfo) const
486 {
487 std::string bundleName = request->GetOwnerBundleName();
488 int32_t userId = request->GetOwnerUserId();
489 if (userId == SUBSCRIBE_USER_INIT) {
490 OsAccountManagerHelper::GetInstance().GetCurrentActiveUserId(userId);
491 }
492 std::shared_ptr<AAFwk::WantParams> extendInfo = request->GetExtendInfo();
493 if (extendInfo == nullptr) {
494 extendInfo = std::make_shared<AAFwk::WantParams>();
495 }
496 extendInfo->SetParam(EXTEND_INFO_PRE + "_" + EXTEND_INFO_APP_NAME, AAFwk::String::Box(appInfo.name));
497 extendInfo->SetParam(EXTEND_INFO_PRE + "_" + EXTEND_INFO_APP_LABEL,
498 AAFwk::String::Box(bundleResourceInfo.label));
499 extendInfo->SetParam(EXTEND_INFO_PRE + "_" + EXTEND_INFO_APP_INDEX,
500 AAFwk::Integer::Box(appInfo.appIndex));
501
502 extendInfo->SetParam(EXTEND_INFO_PRE + "_" + EXTEND_INFO_DEVICE_ID + "_" + deviceType,
503 AAFwk::String::Box(deviceStatus.deviceId));
504 extendInfo->SetParam(EXTEND_INFO_PRE + "_" + EXTEND_INFO_USER_ID + "_" + deviceType,
505 AAFwk::Integer::Box(deviceStatus.userId));
506 request->SetExtendInfo(extendInfo);
507 ANS_LOGI("FillRequestExtendInfo result: %{public}s %{public}s %{public}d %{public}s %{public}d",
508 appInfo.name.c_str(), bundleResourceInfo.label.c_str(), appInfo.appIndex,
509 StringAnonymous(deviceStatus.deviceId).c_str(), deviceStatus.userId);
510 }
511
HandleReminderMethods(const string & deviceType,const map<string,vector<shared_ptr<ReminderAffected>>> & reminderFilterDevice,const sptr<NotificationRequest> & request,set<string> & syncDevices,set<string> & smartDevices,shared_ptr<NotificationFlags> defaultFlag,map<string,bitset<DistributedDeviceStatus::STATUS_SIZE>> & statusMap,shared_ptr<map<string,shared_ptr<NotificationFlags>>> notificationFlagsOfDevices) const512 void SmartReminderCenter::HandleReminderMethods(
513 const string &deviceType,
514 const map<string, vector<shared_ptr<ReminderAffected>>> &reminderFilterDevice,
515 const sptr<NotificationRequest> &request,
516 set<string> &syncDevices,
517 set<string> &smartDevices,
518 shared_ptr<NotificationFlags> defaultFlag,
519 map<string, bitset<DistributedDeviceStatus::STATUS_SIZE>> &statusMap,
520 shared_ptr<map<string, shared_ptr<NotificationFlags>>> notificationFlagsOfDevices) const
521 {
522 std::string classfication = request->GetClassification();
523
524 if (syncDevices.find(deviceType) == syncDevices.end()) {
525 return;
526 }
527
528 if (request->GetClassification() == NotificationConstant::ANS_VOIP) {
529 ANS_LOGI("VOIP CALL");
530 if (deviceType.compare(NotificationConstant::CURRENT_DEVICE_TYPE) == 0) {
531 return;
532 }
533 }
534
535 auto flag = std::make_shared<NotificationFlags>(defaultFlag->GetReminderFlags());
536 if (smartDevices.find(deviceType) == smartDevices.end()) {
537 (*notificationFlagsOfDevices)[deviceType] = flag;
538 ANS_LOGI("default remindFlags, deviceType = %{public}s , remindFlags = %{public}d",
539 deviceType.c_str(), defaultFlag->GetReminderFlags());
540 return;
541 }
542
543 if (deviceType.compare(NotificationConstant::CURRENT_DEVICE_TYPE) == 0 &&
544 smartDevices.size() <= 1) {
545 (*notificationFlagsOfDevices)[deviceType] = flag;
546 ANS_LOGI("default remindFlags, deviceType = %{public}s , remindFlags = %{public}d",
547 deviceType.c_str(), defaultFlag->GetReminderFlags());
548 return;
549 }
550
551 vector<shared_ptr<ReminderAffected>> reminderAffecteds;
552 GetReminderAffecteds(reminderFilterDevice, request, reminderAffecteds);
553 if (reminderAffecteds.size() <= 0) {
554 ANS_LOGI("not set any rule for deviceType %{public}s", deviceType.c_str());
555 return;
556 }
557
558 auto iter = statusMap.find(deviceType);
559 if (iter == statusMap.end()) {
560 ANS_LOGE("get device status failed. deviceType = %{public}s", deviceType.c_str());
561 return;
562 }
563 bitset<DistributedDeviceStatus::STATUS_SIZE> bitStatus = iter->second;
564
565 for (auto &reminderAffected : reminderAffecteds) {
566 if (!CompareStatus(reminderAffected->status_, bitStatus)) {
567 continue;
568 }
569 if (reminderAffected->affectedBy_.size() <= 0) {
570 auto flag = std::make_shared<NotificationFlags>(reminderAffected->reminderFlags_->GetReminderFlags());
571 (*notificationFlagsOfDevices)[deviceType] = flag;
572 ANS_LOGI("smart rule matched, deviceType = %{public}s , remindFlags = %{public}d",
573 deviceType.c_str(), reminderAffected->reminderFlags_->GetReminderFlags());
574 return;
575 } else {
576 bool matched =
577 HandleAffectedReminder(deviceType, reminderAffected, smartDevices, statusMap, notificationFlagsOfDevices);
578 if (matched) {
579 ANS_LOGI("smart rule matched, deviceType = %{public}s , remindFlags = %{public}d",
580 deviceType.c_str(), reminderAffected->reminderFlags_->GetReminderFlags());
581 return;
582 }
583 }
584 }
585 ANS_LOGI("not match any rule. deviceType = %{public}s", deviceType.c_str());
586 }
587
IsNeedSynergy(const NotificationConstant::SlotType & slotType,const string & deviceType,const string & ownerBundleName,int32_t ownerUid) const588 bool SmartReminderCenter::IsNeedSynergy(const NotificationConstant::SlotType &slotType,
589 const string &deviceType, const string &ownerBundleName, int32_t ownerUid) const
590 {
591 std::string device = deviceType;
592 if (deviceType.compare(NotificationConstant::WEARABLE_DEVICE_TYPE) == 0) {
593 device = NotificationConstant::LITEWEARABLE_DEVICE_TYPE;
594 }
595
596 bool isEnable = true;
597 if (NotificationPreferences::GetInstance()->IsSmartReminderEnabled(device, isEnable) != ERR_OK || !isEnable) {
598 ANS_LOGI("switch-status, smartReminderEnable closed. device = %{public}s", device.c_str());
599 return false;
600 }
601
602 sptr<NotificationBundleOption> bundleOption =
603 new (std::nothrow) NotificationBundleOption(ownerBundleName, ownerUid);
604 if (NotificationPreferences::GetInstance()->IsDistributedEnabledByBundle(
605 bundleOption, device, isEnable) != ERR_OK || !isEnable) {
606 ANS_LOGI("switch-status, app switch closed. device = %{public}s", device.c_str());
607 return false;
608 }
609 return true;
610 }
611
GetAppSwitch(const string & deviceType,const string & ownerBundleName,int32_t ownerUid) const612 bool SmartReminderCenter::GetAppSwitch(const string &deviceType,
613 const string &ownerBundleName, int32_t ownerUid) const
614 {
615 std::string device = deviceType;
616 if (deviceType.compare(NotificationConstant::WEARABLE_DEVICE_TYPE) == 0) {
617 device = NotificationConstant::LITEWEARABLE_DEVICE_TYPE;
618 }
619
620 bool isEnable = true;
621
622 sptr<NotificationBundleOption> bundleOption =
623 new (std::nothrow) NotificationBundleOption(ownerBundleName, ownerUid);
624 if (NotificationPreferences::GetInstance()->IsDistributedEnabledByBundle(
625 bundleOption, device, isEnable) != ERR_OK || !isEnable) {
626 return false;
627 }
628 return true;
629 }
630
GetSmartSwitch(const string & deviceType) const631 bool SmartReminderCenter::GetSmartSwitch(const string &deviceType) const
632 {
633 std::string device = deviceType;
634 if (deviceType.compare(NotificationConstant::WEARABLE_DEVICE_TYPE) == 0) {
635 device = NotificationConstant::LITEWEARABLE_DEVICE_TYPE;
636 }
637
638 bool isEnable = true;
639 if (NotificationPreferences::GetInstance()->IsSmartReminderEnabled(device, isEnable) != ERR_OK || !isEnable) {
640 return false;
641 }
642 return true;
643 }
644
GetDistributedSwitch(const string & deviceType) const645 bool SmartReminderCenter::GetDistributedSwitch(const string &deviceType) const
646 {
647 std::string device = deviceType;
648
649 if (deviceType.compare(NotificationConstant::WEARABLE_DEVICE_TYPE) != 0 &&
650 deviceType.compare(NotificationConstant::LITEWEARABLE_DEVICE_TYPE) != 0) {
651 return true;
652 }
653 NotificationConstant::SWITCH_STATE enableStatus;
654 ErrCode errResult = NotificationPreferences::GetInstance()->IsDistributedEnabled(
655 NotificationConstant::LITEWEARABLE_DEVICE_TYPE, enableStatus);
656 if (errResult != ERR_OK) {
657 ANS_LOGE("query distributed switch fail");
658 return false;
659 }
660 if (enableStatus == NotificationConstant::SWITCH_STATE::USER_MODIFIED_ON ||
661 enableStatus == NotificationConstant::SWITCH_STATE::SYSTEM_DEFAULT_ON) {
662 return true;
663 }
664 return false;
665 }
666
HandleAffectedReminder(const string & deviceType,const shared_ptr<ReminderAffected> & reminderAffected,const set<string> & smartDevices,map<string,bitset<DistributedDeviceStatus::STATUS_SIZE>> & statusMap,shared_ptr<map<string,shared_ptr<NotificationFlags>>> notificationFlagsOfDevices) const667 bool SmartReminderCenter::HandleAffectedReminder(
668 const string &deviceType,
669 const shared_ptr<ReminderAffected> &reminderAffected,
670 const set<string> &smartDevices,
671 map<string, bitset<DistributedDeviceStatus::STATUS_SIZE>> &statusMap,
672 shared_ptr<map<string, shared_ptr<NotificationFlags>>> notificationFlagsOfDevices) const
673 {
674 bool ret = true;
675 for (auto &affectedBy : reminderAffected->affectedBy_) {
676 if (smartDevices.find(affectedBy.first) == smartDevices.end()) {
677 ret = false;
678 break;
679 }
680
681 auto iter = statusMap.find(affectedBy.first);
682 if (iter == statusMap.end()) {
683 ANS_LOGE("get device status failed. deviceType = %{public}s", deviceType.c_str());
684 ret = false;
685 break;
686 }
687 bitset<DistributedDeviceStatus::STATUS_SIZE> bitStatus = iter->second;
688
689 if (!CompareStatus(affectedBy.second, bitStatus)) {
690 ret = false;
691 break;
692 }
693 }
694 if (ret) {
695 auto flag = std::make_shared<NotificationFlags>(reminderAffected->reminderFlags_->GetReminderFlags());
696 (*notificationFlagsOfDevices)[deviceType] = flag;
697 }
698 return ret;
699 }
700
CompareStatus(const string & status,const bitset<DistributedDeviceStatus::STATUS_SIZE> & bitStatus) const701 bool SmartReminderCenter::CompareStatus(
702 const string &status, const bitset<DistributedDeviceStatus::STATUS_SIZE> &bitStatus) const
703 {
704 if (status.size() <= 0) {
705 return true;
706 }
707 std::vector<std::string> statusVector;
708 StringUtils::Split(status, StringUtils::SPLIT_CHAR, statusVector);
709 for (std::string strStatus : statusVector) {
710 // bitset.to_string() and config is reverse, bit[0] is behind
711 string localStatus = strStatus;
712 reverse(localStatus.begin(), localStatus.end());
713 for (int32_t seq = 0; seq < DistributedDeviceStatus::STATUS_SIZE; seq++) {
714 if (localStatus[seq] != ReminderAffected::STATUS_DEFAULT && bitStatus[seq] != localStatus[seq] - '0') {
715 break;
716 }
717 if (seq == DistributedDeviceStatus::STATUS_SIZE -1) {
718 return true;
719 }
720 }
721 }
722 return false;
723 }
724
GetReminderAffecteds(const map<string,vector<shared_ptr<ReminderAffected>>> & reminderFilterDevice,const sptr<NotificationRequest> & request,vector<shared_ptr<ReminderAffected>> & reminderAffecteds) const725 __attribute__((no_sanitize("cfi"))) void SmartReminderCenter::GetReminderAffecteds(
726 const map<string, vector<shared_ptr<ReminderAffected>>> &reminderFilterDevice,
727 const sptr<NotificationRequest> &request,
728 vector<shared_ptr<ReminderAffected>> &reminderAffecteds) const
729 {
730 string strSlotType = to_string(static_cast<int32_t>(request->GetSlotType()));
731 string contentTypeCombination = strSlotType;
732 contentTypeCombination.append("#");
733 if (request->GetContent() != nullptr) {
734 contentTypeCombination.append(to_string(static_cast<int32_t>(request->GetContent()->GetContentType())));
735 }
736 string typeCodeCombination = contentTypeCombination;
737 typeCodeCombination.append("#");
738 if (request->GetContent() != nullptr && request->GetContent()->GetNotificationContent() != nullptr) {
739 NotificationLocalLiveViewContent *localLiveView =
740 static_cast<NotificationLocalLiveViewContent *>(&(*(request->GetContent()->GetNotificationContent())));
741 typeCodeCombination.append(to_string(localLiveView->GetType()));
742 }
743 auto iter = reminderFilterDevice.find(typeCodeCombination);
744 if (iter != reminderFilterDevice.end()) {
745 reminderAffecteds = iter->second;
746 return;
747 }
748 iter = reminderFilterDevice.find(contentTypeCombination);
749 if (iter != reminderFilterDevice.end()) {
750 reminderAffecteds = iter->second;
751 return;
752 }
753 iter = reminderFilterDevice.find(strSlotType);
754 if (iter != reminderFilterDevice.end()) {
755 reminderAffecteds = iter->second;
756 return;
757 }
758 ANS_LOGD("GetReminderAffecteds fail as wrong notification_config.json possibly. TypeCombination = %{public}s.",
759 typeCodeCombination.c_str());
760 }
761
GetDeviceStatusByType(const string & deviceType,bitset<DistributedDeviceStatus::STATUS_SIZE> & bitStatus) const762 void SmartReminderCenter::GetDeviceStatusByType(
763 const string &deviceType, bitset<DistributedDeviceStatus::STATUS_SIZE> &bitStatus) const
764 {
765 u_int32_t status = DelayedSingleton<DistributedDeviceStatus>::GetInstance()->GetDeviceStatus(deviceType);
766 bitStatus = bitset<DistributedDeviceStatus::STATUS_SIZE>(status);
767 if (deviceType.compare(NotificationConstant::CURRENT_DEVICE_TYPE) == 0) {
768 bool screenLocked = true;
769 screenLocked = ScreenLock::ScreenLockManager::GetInstance()->IsScreenLocked();
770 bitStatus.set(DistributedDeviceStatus::LOCK_FLAG, !screenLocked);
771 }
772 ANS_LOGI("deviceType: %{public}s, bitStatus: %{public}s", deviceType.c_str(), bitStatus.to_string().c_str());
773 }
774 } // namespace Notification
775 } // namespace OHOS
776 #endif
777