1 /*
2  * Copyright (c) 2022 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 "notification_tools.h"
17 
18 #include <sstream>
19 #ifdef DISTRIBUTED_NOTIFICATION_ENABLE
20 #include "notification_helper.h"
21 #endif
22 #include "continuous_task_log.h"
23 #include "string_wrapper.h"
24 
25 #ifdef BGTASK_MGR_UNIT_TEST
26 #define WEAK_FUNC __attribute__((weak))
27 #else
28 #define WEAK_FUNC
29 #endif
30 
31 namespace OHOS {
32 namespace BackgroundTaskMgr {
33 namespace {
34 constexpr char NOTIFICATION_PREFIX[] = "bgmode";
35 constexpr char SEPARATOR[] = "_";
36 #ifdef DISTRIBUTED_NOTIFICATION_ENABLE
37 constexpr int BACKGROUND_MODE_DATA_TANSFER = 1;
38 constexpr int BACKGROUND_MODE_AUDIO_RECORDING = 3;
39 constexpr int BACKGROUND_MODE_VOIP = 8;
40 constexpr int PUBLISH_DELAY_TIME = 3;
41 constexpr int TYPE_CODE_VOIP = 0;
42 constexpr int TYPE_CODE_AUDIO_RECORDING = 7;
43 constexpr int TYPE_CODE_DATA_TANSFER = 8;
44 #endif
45 }
46 
47 int32_t NotificationTools::notificationIdIndex_ = -1;
NotificationTools()48 NotificationTools::NotificationTools() {}
49 
~NotificationTools()50 NotificationTools::~NotificationTools() {}
51 
SetNotificationIdIndex(const int32_t id)52 void NotificationTools::SetNotificationIdIndex(const int32_t id)
53 {
54     notificationIdIndex_ = id;
55 }
56 
CreateNotificationLabel(int32_t uid,const std::string & bundleName,const std::string & abilityName,int32_t abilityId)57 std::string CreateNotificationLabel(int32_t uid, const std::string &bundleName,
58     const std::string &abilityName, int32_t abilityId)
59 {
60     std::stringstream stream;
61     stream.clear();
62     stream.str("");
63     stream << NOTIFICATION_PREFIX << SEPARATOR << uid << SEPARATOR << std::hash<std::string>()(abilityName) <<
64         SEPARATOR << abilityId;
65     std::string label = stream.str();
66     BGTASK_LOGD("notification label: %{public}s", label.c_str());
67     return label;
68 }
69 
PublishNotification(const std::shared_ptr<ContinuousTaskRecord> & continuousTaskRecord,const std::string & appName,const std::string & prompt,int32_t serviceUid)70 WEAK_FUNC ErrCode NotificationTools::PublishNotification(
71     const std::shared_ptr<ContinuousTaskRecord> &continuousTaskRecord,
72     const std::string &appName, const std::string &prompt, int32_t serviceUid)
73 {
74 #ifdef DISTRIBUTED_NOTIFICATION_ENABLE
75     std::shared_ptr<Notification::NotificationLocalLiveViewContent> liveContent
76         = std::make_shared<Notification::NotificationLocalLiveViewContent>();
77     liveContent->SetTitle(appName);
78     liveContent->SetText(prompt);
79     if (std::find(continuousTaskRecord->bgModeIds_.begin(), continuousTaskRecord->bgModeIds_.end(),
80         BACKGROUND_MODE_DATA_TANSFER) != continuousTaskRecord->bgModeIds_.end()) {
81         liveContent->SetType(TYPE_CODE_DATA_TANSFER);
82     } else if (std::find(continuousTaskRecord->bgModeIds_.begin(), continuousTaskRecord->bgModeIds_.end(),
83         BACKGROUND_MODE_AUDIO_RECORDING) != continuousTaskRecord->bgModeIds_.end()) {
84         liveContent->SetType(TYPE_CODE_AUDIO_RECORDING);
85     } else if (std::find(continuousTaskRecord->bgModeIds_.begin(), continuousTaskRecord->bgModeIds_.end(),
86         BACKGROUND_MODE_VOIP) != continuousTaskRecord->bgModeIds_.end()) {
87         liveContent->SetType(TYPE_CODE_VOIP);
88     }
89 
90     std::shared_ptr<AAFwk::WantParams> extraInfo = std::make_shared<AAFwk::WantParams>();
91     extraInfo->SetParam("abilityName", AAFwk::String::Box(continuousTaskRecord->abilityName_));
92 
93     std::string notificationLabel = CreateNotificationLabel(continuousTaskRecord->uid_,
94         continuousTaskRecord->bundleName_, continuousTaskRecord->abilityName_,
95         continuousTaskRecord->abilityId_);
96 
97     Notification::NotificationRequest notificationRequest = Notification::NotificationRequest();
98     notificationRequest.SetContent(std::make_shared<Notification::NotificationContent>(liveContent));
99     notificationRequest.SetAdditionalData(extraInfo);
100     notificationRequest.SetWantAgent(continuousTaskRecord->wantAgent_);
101     notificationRequest.SetCreatorUid(serviceUid);
102     notificationRequest.SetOwnerUid(continuousTaskRecord->GetUid());
103     notificationRequest.SetInProgress(true);
104     notificationRequest.SetIsAgentNotification(true);
105     notificationRequest.SetPublishDelayTime(PUBLISH_DELAY_TIME);
106     notificationRequest.SetUpdateByOwnerAllowed(true);
107     notificationRequest.SetSlotType(Notification::NotificationConstant::SlotType::LIVE_VIEW);
108     notificationRequest.SetLabel(notificationLabel);
109     if (continuousTaskRecord->GetNotificationId() == -1) {
110         notificationRequest.SetNotificationId(++notificationIdIndex_);
111     } else {
112         notificationRequest.SetNotificationId(continuousTaskRecord->GetNotificationId());
113     }
114     if (Notification::NotificationHelper::PublishNotification(notificationRequest) != ERR_OK) {
115         BGTASK_LOGE("publish notification error, %{public}s, %{public}d", notificationLabel.c_str(),
116             continuousTaskRecord->notificationId_);
117         return ERR_BGTASK_NOTIFICATION_ERR;
118     }
119     continuousTaskRecord->notificationLabel_ = notificationLabel;
120     if (continuousTaskRecord->GetNotificationId() == -1) {
121         continuousTaskRecord->notificationId_ = notificationIdIndex_;
122     }
123 #endif
124     return ERR_OK;
125 }
126 
CancelNotification(const std::string & label,int32_t id)127 WEAK_FUNC ErrCode NotificationTools::CancelNotification(const std::string &label, int32_t id)
128 {
129 #ifdef DISTRIBUTED_NOTIFICATION_ENABLE
130     if (Notification::NotificationHelper::CancelNotification(label, id) != ERR_OK) {
131         BGTASK_LOGE("CancelNotification error label %{public}s, id %{public}d", label.c_str(), id);
132         return ERR_BGTASK_NOTIFICATION_ERR;
133     }
134 #endif
135     return ERR_OK;
136 }
137 
GetAllActiveNotificationsLabels(std::set<std::string> & notificationLabels)138 WEAK_FUNC void NotificationTools::GetAllActiveNotificationsLabels(std::set<std::string> &notificationLabels)
139 {
140 #ifdef DISTRIBUTED_NOTIFICATION_ENABLE
141     std::vector<sptr<Notification::Notification>> notifications;
142     ErrCode ret = Notification::NotificationHelper::GetAllActiveNotifications(notifications);
143     if (ret != ERR_OK) {
144         BGTASK_LOGE("get all active notification fail!");
145         return;
146     }
147     for (auto &var : notifications) {
148         notificationLabels.emplace(var->GetLabel());
149     }
150 #endif
151 }
152 
RefreshContinuousNotifications(const std::map<std::string,std::pair<std::string,std::string>> & newPromptInfos,int32_t serviceUid)153 WEAK_FUNC void NotificationTools::RefreshContinuousNotifications(
154     const std::map<std::string, std::pair<std::string, std::string>> &newPromptInfos, int32_t serviceUid)
155 {
156 #ifdef DISTRIBUTED_NOTIFICATION_ENABLE
157     std::vector<sptr<Notification::Notification>> notifications;
158     ErrCode ret = Notification::NotificationHelper::GetAllActiveNotifications(notifications);
159     if (ret != ERR_OK) {
160         BGTASK_LOGE("get all active notification fail!");
161         return;
162     }
163     for (auto &var : notifications) {
164         Notification::NotificationRequest request = var->GetNotificationRequest();
165         std::string label = var->GetLabel();
166         if (newPromptInfos.count(label) == 0 || request.GetCreatorUid() != serviceUid) {
167             continue;
168         }
169         auto &content = request.GetContent();
170         auto const &normalContent = content->GetNotificationContent();
171         normalContent->SetTitle(newPromptInfos.at(label).first);
172         normalContent->SetText(newPromptInfos.at(label).second);
173         if (Notification::NotificationHelper::PublishContinuousTaskNotification(request) != ERR_OK) {
174             BGTASK_LOGE("refresh notification error");
175         }
176     }
177 #endif
178 }
179 }
180 }
181