1 /*
2 * Copyright (c) 2023-2023 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 "advanced_notification_service.h"
17
18 #include "errors.h"
19 #include "ans_inner_errors.h"
20 #include "notification_record.h"
21 #include "notification_request.h"
22 #include "want_params_wrapper.h"
23 #include "notification_preferences.h"
24 #include "access_token_helper.h"
25 #include "accesstoken_kit.h"
26 #include "ipc_skeleton.h"
27
28 namespace OHOS {
29 namespace Notification {
RecoverLiveViewFromDb()30 void AdvancedNotificationService::RecoverLiveViewFromDb()
31 {
32 ANS_LOGI("Start recover live view from db.");
33
34 std::vector<NotificationRequestDb> requestsdb;
35 if (GetBatchNotificationRequestsFromDb(requestsdb) != ERR_OK) {
36 ANS_LOGE("Get liveView from db failed.");
37 return;
38 }
39
40 for (const auto &requestObj : requestsdb) {
41 ANS_LOGD("Recover request: %{public}s.", requestObj.request->Dump().c_str());
42 if (!IsLiveViewCanRecover(requestObj.request)) {
43 if (DeleteNotificationRequestFromDb(requestObj.request->GetKey()) != ERR_OK) {
44 ANS_LOGE("Delete notification failed.");
45 }
46 continue;
47 }
48
49 auto record = std::make_shared<NotificationRecord>();
50 if (FillNotificationRecord(requestObj, record) != ERR_OK) {
51 ANS_LOGE("Fill notification record failed.");
52 continue;
53 }
54
55 if (Filter(record, true) != ERR_OK) {
56 ANS_LOGE("Filter record failed.");
57 continue;
58 }
59
60 if (AssignToNotificationList(record) != ERR_OK) {
61 ANS_LOGE("Add notification to record list failed.");
62 continue;
63 }
64 UpdateRecentNotification(record->notification, false, 0);
65
66 StartFinishTimer(record, requestObj.request->GetFinishDeadLine());
67 StartUpdateTimer(record, requestObj.request->GetUpdateDeadLine());
68 }
69
70 // publish notifications
71 for (const auto &subscriber : NotificationSubscriberManager::GetInstance()->GetSubscriberRecords()) {
72 OnSubscriberAdd(subscriber);
73 }
74
75 ANS_LOGI("End recover live view from db.");
76 }
77
UpdateNotificationTimerInfo(const std::shared_ptr<NotificationRecord> & record)78 ErrCode AdvancedNotificationService::UpdateNotificationTimerInfo(const std::shared_ptr<NotificationRecord> &record)
79 {
80 ErrCode result = ERR_OK;
81
82 if (!record->request->IsCommonLiveView()) {
83 return ERR_OK;
84 }
85
86 auto content = record->request->GetContent()->GetNotificationContent();
87 auto liveViewContent = std::static_pointer_cast<NotificationLiveViewContent>(content);
88 auto status = liveViewContent->GetLiveViewStatus();
89 switch (status) {
90 case NotificationLiveViewContent::LiveViewStatus::LIVE_VIEW_CREATE:
91 result = SetFinishTimer(record);
92 if (result != ERR_OK) {
93 return result;
94 }
95
96 result = SetUpdateTimer(record);
97 return result;
98 case NotificationLiveViewContent::LiveViewStatus::LIVE_VIEW_INCREMENTAL_UPDATE:
99 case NotificationLiveViewContent::LiveViewStatus::LIVE_VIEW_FULL_UPDATE:
100 // delete old, then add new
101 CancelUpdateTimer(record);
102 result = SetUpdateTimer(record);
103 return result;
104
105 case NotificationLiveViewContent::LiveViewStatus::LIVE_VIEW_END:
106 CancelUpdateTimer(record);
107 CancelFinishTimer(record);
108 StartArchiveTimer(record);
109 break;
110 default:
111 ANS_LOGE("Invalid status %{public}d.", status);
112 return ERR_ANS_INVALID_PARAM;
113 }
114 return result;
115 }
116
ProcForDeleteLiveView(const std::shared_ptr<NotificationRecord> & record)117 void AdvancedNotificationService::ProcForDeleteLiveView(const std::shared_ptr<NotificationRecord> &record)
118 {
119 if ((record->request == nullptr) || !(record->request->IsCommonLiveView())) {
120 return;
121 }
122
123 if (DeleteNotificationRequestFromDb(record->request->GetKey()) != ERR_OK) {
124 ANS_LOGE("Live View cancel, delete notification failed.");
125 }
126
127 CancelUpdateTimer(record);
128 CancelFinishTimer(record);
129 CancelArchiveTimer(record);
130 }
131
OnSubscriberAdd(const std::shared_ptr<NotificationSubscriberManager::SubscriberRecord> & record)132 void AdvancedNotificationService::OnSubscriberAdd(
133 const std::shared_ptr<NotificationSubscriberManager::SubscriberRecord> &record)
134 {
135 if (record == nullptr) {
136 ANS_LOGE("No subscriber to notify.");
137 return;
138 }
139
140 sptr<NotificationSortingMap> sortingMap = GenerateSortingMap();
141 std::vector<sptr<Notification>> notifications;
142 for (auto notificationRecord : notificationList_) {
143 if (notificationRecord->notification != nullptr &&
144 notificationRecord->notification->GetNotificationRequest().IsCommonLiveView()) {
145 notifications.emplace_back(notificationRecord->notification);
146 }
147 }
148
149 if (notifications.empty()) {
150 ANS_LOGI("No notification to consume.");
151 return;
152 }
153
154 ANS_LOGI("Consume notification count is %{public}zu.", notifications.size());
155 NotificationSubscriberManager::GetInstance()->BatchNotifyConsumed(notifications, sortingMap, record);
156 }
157
IsLiveViewCanRecover(const sptr<NotificationRequest> request)158 bool AdvancedNotificationService::IsLiveViewCanRecover(const sptr<NotificationRequest> request)
159 {
160 if (request == nullptr) {
161 ANS_LOGE("Invalid liveview.");
162 return false;
163 }
164
165 using StatusType = NotificationLiveViewContent::LiveViewStatus;
166 auto liveViewContent =
167 std::static_pointer_cast<NotificationLiveViewContent>(request->GetContent()->GetNotificationContent());
168 auto liveViewStatus = liveViewContent->GetLiveViewStatus();
169 if (liveViewStatus == StatusType::LIVE_VIEW_BUTT || liveViewStatus == StatusType::LIVE_VIEW_END) {
170 ANS_LOGE("Only update or create status can reconver.");
171 return false;
172 }
173
174 auto epoch = std::chrono::system_clock::now().time_since_epoch();
175 auto curTime = std::chrono::duration_cast<std::chrono::milliseconds>(epoch).count();
176 if (curTime > request->GetUpdateDeadLine() || curTime > request->GetFinishDeadLine()) {
177 ANS_LOGE("The liveView has expired.");
178 return false;
179 }
180
181 return true;
182 }
183
SetNotificationRequestToDb(const NotificationRequestDb & requestDb)184 int32_t AdvancedNotificationService::SetNotificationRequestToDb(const NotificationRequestDb &requestDb)
185 {
186 auto request = requestDb.request;
187 if (!request->IsCommonLiveView()) {
188 ANS_LOGD("Slot type %{public}d, content type %{public}d.",
189 request->GetSlotType(), request->GetNotificationType());
190
191 return ERR_OK;
192 }
193
194 ANS_LOGI("Enter.");
195 auto content = std::static_pointer_cast<NotificationLiveViewContent>(
196 request->GetContent()->GetNotificationContent());
197 if (content->GetLiveViewStatus() == NotificationLiveViewContent::LiveViewStatus::LIVE_VIEW_END &&
198 request->GetAutoDeletedTime() == NotificationConstant::NO_DELAY_DELETE_TIME) {
199 ANS_LOGI("Don't need set to db when liveview is in end status and no delay delete time.");
200 return ERR_OK;
201 }
202
203 nlohmann::json jsonObject;
204 if (!NotificationJsonConverter::ConvertToJson(request, jsonObject)) {
205 ANS_LOGE("Convert request to json object failed, bundle name %{public}s, id %{public}d.",
206 request->GetCreatorBundleName().c_str(), request->GetNotificationId());
207 return ERR_ANS_TASK_ERR;
208 }
209 auto bundleOption = requestDb.bundleOption;
210 if (!NotificationJsonConverter::ConvertToJson(bundleOption, jsonObject)) {
211 ANS_LOGE("Convert bundle to json object failed, bundle name %{public}s, id %{public}d.",
212 bundleOption->GetBundleName().c_str(), request->GetNotificationId());
213 return ERR_ANS_TASK_ERR;
214 }
215
216 auto result = NotificationPreferences::GetInstance().SetKvToDb(request->GetKey(), jsonObject.dump());
217 if (result != ERR_OK) {
218 ANS_LOGE(
219 "Set notification request failed, bundle name %{public}s, id %{public}d, key %{public}s, ret %{public}d.",
220 request->GetCreatorBundleName().c_str(), request->GetNotificationId(), request->GetKey().c_str(), result);
221 return result;
222 }
223 return ERR_OK;
224 }
225
GetNotificationRequestFromDb(const std::string & key,NotificationRequestDb & requestDb)226 int32_t AdvancedNotificationService::GetNotificationRequestFromDb(
227 const std::string &key, NotificationRequestDb &requestDb)
228 {
229 std::string value;
230 int32_t result = NotificationPreferences::GetInstance().GetKvFromDb(key, value);
231 if (result != ERR_OK) {
232 ANS_LOGE("Get notification request failed, key %{public}s.", key.c_str());
233 return result;
234 }
235 auto jsonObject = nlohmann::json::parse(value);
236 auto *request = NotificationJsonConverter::ConvertFromJson<NotificationRequest>(jsonObject);
237 if (request == nullptr) {
238 ANS_LOGE("Parse json string to request failed, str: %{public}s.", value.c_str());
239 return ERR_ANS_TASK_ERR;
240 }
241 auto *bundleOption = NotificationJsonConverter::ConvertFromJson<NotificationBundleOption>(jsonObject);
242 if (bundleOption == nullptr) {
243 ANS_LOGE("Parse json string to bundle option failed, str: %{public}s.", value.c_str());
244 return ERR_ANS_TASK_ERR;
245 }
246 requestDb.request = request;
247 requestDb.bundleOption = bundleOption;
248 return ERR_OK;
249 }
250
GetBatchNotificationRequestsFromDb(std::vector<NotificationRequestDb> & requests)251 int32_t AdvancedNotificationService::GetBatchNotificationRequestsFromDb(std::vector<NotificationRequestDb> &requests)
252 {
253 std::unordered_map<std::string, std::string> dbRecords;
254 int32_t result =
255 NotificationPreferences::GetInstance().GetBatchKvsFromDb(REQUEST_STORAGE_KEY_PREFIX, dbRecords);
256 if (result != ERR_OK) {
257 ANS_LOGE("Get batch notification request failed.");
258 return result;
259 }
260 for (const auto &iter : dbRecords) {
261 auto jsonObject = nlohmann::json::parse(iter.second);
262 auto *request = NotificationJsonConverter::ConvertFromJson<NotificationRequest>(jsonObject);
263 if (request == nullptr) {
264 ANS_LOGE("Parse json string to request failed.");
265 continue;
266 }
267 auto *bundleOption = NotificationJsonConverter::ConvertFromJson<NotificationBundleOption>(jsonObject);
268 if (bundleOption == nullptr) {
269 ANS_LOGE("Parse json string to bundle option failed.");
270 (void)DeleteNotificationRequestFromDb(request->GetKey());
271 continue;
272 }
273 NotificationRequestDb requestDb = { .request = request, .bundleOption = bundleOption };
274 requests.emplace_back(requestDb);
275 }
276 return ERR_OK;
277 }
278
DeleteNotificationRequestFromDb(const std::string & key)279 int32_t AdvancedNotificationService::DeleteNotificationRequestFromDb(const std::string &key)
280 {
281 auto result = NotificationPreferences::GetInstance().DeleteKvFromDb(key);
282 if (result != ERR_OK) {
283 ANS_LOGE("Delete notification request failed, key %{public}s.", key.c_str());
284 return result;
285 }
286 return ERR_OK;
287 }
288
IsAllowedRemoveSlot(const sptr<NotificationBundleOption> & bundleOption,const NotificationConstant::SlotType & slotType)289 ErrCode AdvancedNotificationService::IsAllowedRemoveSlot(const sptr<NotificationBundleOption> &bundleOption,
290 const NotificationConstant::SlotType &slotType)
291 {
292 if (slotType != NotificationConstant::SlotType::LIVE_VIEW) {
293 return ERR_OK;
294 }
295
296 sptr<NotificationSlot> slot;
297 if (NotificationPreferences::GetInstance().GetNotificationSlot(bundleOption, slotType, slot) != ERR_OK) {
298 ANS_LOGE("Failed to get slot.");
299 return ERR_OK;
300 }
301
302 if (!slot->GetForceControl()) {
303 ANS_LOGI("Liveview slot is not force control.");
304 return ERR_OK;
305 }
306
307 bool isSubsystem = AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID());
308 if (!isSubsystem && !AccessTokenHelper::IsSystemApp()) {
309 ANS_LOGE("Only sa or systemapp can remove liveview slot.");
310 return ERR_ANS_NON_SYSTEM_APP;
311 }
312
313 return ERR_OK;
314 }
315 }
316 }
317