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