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 #ifdef NOTIFICATION_SMART_REMINDER_SUPPORTED
16 #include "reminder_swing_decision_center.h"
17 #include "notification_preferences.h"
18 #include "smart_reminder_center.h"
19 #include "reminder_affected.h"
20
21 namespace OHOS {
22 namespace Notification {
23 using namespace std;
24 mutex ReminderSwingDecisionCenter::swingMutex_;
25 sptr<ISwingCallBack> ReminderSwingDecisionCenter::swingCallback_ = nullptr;
26
ReminderSwingDecisionCenter()27 ReminderSwingDecisionCenter::ReminderSwingDecisionCenter()
28 {}
29
~ReminderSwingDecisionCenter()30 ReminderSwingDecisionCenter::~ReminderSwingDecisionCenter() {}
31
GetInstance()32 ReminderSwingDecisionCenter &ReminderSwingDecisionCenter::GetInstance()
33 {
34 return DelayedRefSingleton<ReminderSwingDecisionCenter>::GetInstance();
35 }
36
RegisterSwingCallback(const sptr<IRemoteObject> & swingCallback)37 ErrCode ReminderSwingDecisionCenter::RegisterSwingCallback(const sptr<IRemoteObject> &swingCallback)
38 {
39 if (swingCallback == nullptr) {
40 ANS_LOGW("swingCallback is null.");
41 return ERR_INVALID_VALUE;
42 }
43 swingRecipient_ = new (nothrow) SwingCallbackRecipient();
44 if (!swingRecipient_) {
45 ANS_LOGE("Failed to create death Recipient ptr SwingCallbackRecipient!");
46 return ERR_NO_INIT;
47 }
48 swingCallback->AddDeathRecipient(swingRecipient_);
49 lock_guard<mutex> lock(swingMutex_);
50 swingCallback_ = iface_cast<ISwingCallBack>(swingCallback);
51 ANS_LOGI("RegisterSwingCallback OK");
52 return ERR_OK;
53 }
54
ResetSwingCallbackProxy()55 void ReminderSwingDecisionCenter::ResetSwingCallbackProxy()
56 {
57 ANS_LOGD("enter");
58 lock_guard<mutex> lock(swingMutex_);
59 if (swingCallback_ == nullptr || swingCallback_->AsObject() == nullptr) {
60 ANS_LOGE("invalid proxy state");
61 return;
62 }
63 swingCallback_->AsObject()->RemoveDeathRecipient(swingRecipient_);
64 swingCallback_ = nullptr;
65 }
66
GetCcmSwingRemind()67 void ReminderSwingDecisionCenter::GetCcmSwingRemind()
68 {
69 nlohmann::json root;
70 string swingJsonPoint = "/";
71 swingJsonPoint.append(NotificationConfigParse::CFG_KEY_NOTIFICATION_SERVICE);
72 swingJsonPoint.append("/");
73 swingJsonPoint.append(SWING_FILTER);
74 swingJsonPoint.append("/");
75 swingJsonPoint.append(AFFTECED_BY);
76 isSupportSwingSmartRemind_ = false;
77 if (!NotificationConfigParse::GetInstance()->GetConfigJson(swingJsonPoint, root)) {
78 ANS_LOGI("Failed to get swingJsonPoint CCM config file.");
79 return;
80 }
81
82 nlohmann::json affects = root[NotificationConfigParse::CFG_KEY_NOTIFICATION_SERVICE][SWING_FILTER][AFFTECED_BY];
83
84 if (affects.is_null() || !affects.is_array() || affects.empty()) {
85 ANS_LOGI("GetCcmSwingRemind failed as invalid ccmSwingRemind json.");
86 return;
87 }
88
89 for (auto &affect : affects) {
90 if (affect.is_null() || !affect.is_object()) {
91 continue;
92 }
93 if (affect[ReminderAffected::DEVICE_TYPE].is_null() ||
94 !affect[ReminderAffected::DEVICE_TYPE].is_string() ||
95 affect[ReminderAffected::STATUS].is_null() ||
96 !affect[ReminderAffected::STATUS].is_string()) {
97 continue;
98 }
99 enableSwingDeviceType_ = affect[ReminderAffected::DEVICE_TYPE].get<string>();
100 enableSwingDeviceStatus_ = affect[ReminderAffected::STATUS].get<string>();
101 ANS_LOGI("GetCcmSwingRemind deviceType: %{public}s status: %{public}s", enableSwingDeviceType_.c_str(),
102 enableSwingDeviceStatus_.c_str());
103 isSupportSwingSmartRemind_ = true;
104 }
105 }
106
GetSwingDeviceType()107 string ReminderSwingDecisionCenter::GetSwingDeviceType()
108 {
109 return enableSwingDeviceType_;
110 }
111
UpdateCrossDeviceNotificationStatus(bool isEnable)112 void ReminderSwingDecisionCenter::UpdateCrossDeviceNotificationStatus(bool isEnable)
113 {
114 isCrossDeviceNotificationEnable_ = isEnable;
115 ANS_LOGD("UpdateCrossDeviceNotificationStatus %{public}d", isEnable);
116 }
117
OnSmartReminderStatusChanged()118 void ReminderSwingDecisionCenter::OnSmartReminderStatusChanged()
119 {
120 SwingExecuteDecision(false);
121 }
122
DisableSwingStatus()123 void ReminderSwingDecisionCenter::DisableSwingStatus()
124 {
125 if (!isSwingExecuting_) {
126 return;
127 }
128 isSwingExecuting_ = false;
129 lock_guard<mutex> lock(swingMutex_);
130 if (swingCallback_ == nullptr) {
131 return;
132 }
133 ANS_LOGD("DisableSwingStatus");
134 swingCallback_->OnUpdateStatus(false, NONE_UNLOCK_TRIGGER);
135 }
136
SwingExecuteDecision(bool isScreenUnlockTrigger)137 void ReminderSwingDecisionCenter::SwingExecuteDecision(bool isScreenUnlockTrigger)
138 {
139 ANS_LOGD("SwingExecuteDecision");
140 if (!isSupportSwingSmartRemind_) {
141 ANS_LOGI("is not SupportSwingSmartRemind");
142 return;
143 }
144
145 if (!isCrossDeviceNotificationEnable_) {
146 ANS_LOGI("crossDeviceNotification disable");
147 DisableSwingStatus();
148 return;
149 }
150
151 bool isSmartReminderEnable = false;
152 if (ERR_OK != NotificationPreferences::GetInstance()->IsSmartReminderEnabled(enableSwingDeviceType_,
153 isSmartReminderEnable)) {
154 ANS_LOGI("IsSmartReminderEnable error");
155 return;
156 }
157
158 if (!isSmartReminderEnable) {
159 ANS_LOGI("IsSmartReminderEnable false");
160 DisableSwingStatus();
161 return;
162 }
163 lock_guard<mutex> lock(swingMutex_);
164 if (swingCallback_ == nullptr) {
165 ANS_LOGI("swingCallback_ is null");
166 return;
167 }
168
169 int triggerMode = isScreenUnlockTrigger ? UNLOCK_TRIGGER : NONE_UNLOCK_TRIGGER;
170 bool isSwingCrossDeviceStatusStatified = IsStatifySwingCrossDeviceStatus();
171 if (isScreenUnlock_ && isSwingCrossDeviceStatusStatified) {
172 if (!isSwingExecuting_) {
173 isSwingExecuting_ = true;
174 swingCallback_->OnUpdateStatus(true, triggerMode);
175 ANS_LOGI("swing OnUpdateStatus enable triggerMode %{public}d", triggerMode);
176 } else {
177 ANS_LOGD("isSwingExecuting_ %{public}d", isSwingExecuting_);
178 }
179 } else {
180 if (isSwingExecuting_) {
181 isSwingExecuting_ = false;
182 swingCallback_->OnUpdateStatus(false, triggerMode);
183 ANS_LOGI("swing OnUpdateStatus disable triggerMode %{public}d", triggerMode);
184 } else {
185 ANS_LOGD("isScreenUnlock_ %{public}d isSwingCrossDeviceStatusStatified %{public}d ",
186 isScreenUnlock_, isSwingCrossDeviceStatusStatified);
187 }
188 }
189 }
190
IsStatifySwingCrossDeviceStatus()191 bool ReminderSwingDecisionCenter::IsStatifySwingCrossDeviceStatus()
192 {
193 uint32_t status =
194 DelayedSingleton<DistributedDeviceStatus>::GetInstance()->GetDeviceStatus(enableSwingDeviceType_);
195 bool isSatisfied = SmartReminderCenter::GetInstance()->CompareStatus(enableSwingDeviceStatus_, bitset<4>(status));
196 return isSatisfied;
197 }
198
OnUpdateDeviceStatus(const std::string & deviceType)199 void ReminderSwingDecisionCenter::OnUpdateDeviceStatus(const std::string &deviceType)
200 {
201 if (deviceType.empty() || enableSwingDeviceType_.empty()) {
202 return;
203 }
204 if (deviceType.compare(enableSwingDeviceType_) == 0) {
205 SwingExecuteDecision(false);
206 }
207 }
208
OnScreenLock()209 void ReminderSwingDecisionCenter::OnScreenLock()
210 {
211 ANS_LOGI("OnScreenLock");
212 if (isScreenUnlock_) {
213 isScreenUnlock_ = false;
214 SwingExecuteDecision(true);
215 }
216 }
217
OnScreenUnlock()218 void ReminderSwingDecisionCenter::OnScreenUnlock()
219 {
220 ANS_LOGI("OnScreenUnlock");
221 if (!isScreenUnlock_) {
222 isScreenUnlock_ = true;
223 SwingExecuteDecision(true);
224 }
225 }
226
OnRemoteDied(const wptr<IRemoteObject> & remote)227 void SwingCallbackRecipient::OnRemoteDied(const wptr<IRemoteObject> &remote)
228 {
229 ANS_LOGI("Swing Callback died, remove the proxy object");
230 ReminderSwingDecisionCenter::GetInstance().ResetSwingCallbackProxy();
231 }
232
SwingCallbackRecipient()233 SwingCallbackRecipient::SwingCallbackRecipient() {}
234
~SwingCallbackRecipient()235 SwingCallbackRecipient::~SwingCallbackRecipient() {}
236 }
237 }
238 #endif