• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &notificationType,
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 &notificationType,
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 &notificationType,
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