1 /*
2 * Copyright (C) 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 #ifndef LOG_TAG
16 #define LOG_TAG "AudioSafeVolumeNotificationImpl"
17 #endif
18
19 #include "audio_safe_volume_notification_impl.h"
20
21 #include <map>
22
23 #include "want_agent_helper.h"
24 #include "want_agent_info.h"
25 #include "notification_helper.h"
26 #include "notification_request.h"
27 #include "notification_constant.h"
28 #include "notification_bundle_option.h"
29 #include "rstate.h"
30 #include "ipc_skeleton.h"
31 #include "audio_policy_log.h"
32 #include "os_account_manager.h"
33 #include "locale_config.h"
34 #include "resource_manager_adapter.h"
35
36 namespace OHOS {
37 namespace AudioStandard {
GetSystemStringByName(std::string name)38 std::string AudioSafeVolumeNotificationImpl::GetSystemStringByName(std::string name)
39 {
40 std::string identity = IPCSkeleton::ResetCallingIdentity();
41 std::string result = ResourceManagerAdapter::GetInstance()->GetSystemStringByName(name);
42 IPCSkeleton::SetCallingIdentity(identity);
43 return result;
44 }
45
SetTitleAndText(int32_t notificationId,std::shared_ptr<Notification::NotificationNormalContent> content)46 bool AudioSafeVolumeNotificationImpl::SetTitleAndText(int32_t notificationId,
47 std::shared_ptr<Notification::NotificationNormalContent> content)
48 {
49 if (content == nullptr) {
50 AUDIO_ERR_LOG("notification normal content nullptr");
51 return false;
52 }
53
54 switch (notificationId) {
55 case RESTORE_VOLUME_NOTIFICATION_ID:
56 content->SetTitle(GetSystemStringByName(SAFE_VOLUME_MUSIC_TIMER_TITTLE_ID));
57 content->SetText(GetSystemStringByName(SAFE_VOLUME_MUSIC_TIMER_TEXT_ID));
58 break;
59 case INCREASE_VOLUME_NOTIFICATION_ID:
60 content->SetTitle(GetSystemStringByName(SAFE_VOLUME_INCREASE_VOLUME_TITTLE_ID));
61 content->SetText(GetSystemStringByName(SAFE_VOLUME_INCREASE_VOLUME_TEXT_ID));
62 break;
63 default:
64 AUDIO_ERR_LOG("error notificationId");
65 return false;
66 }
67 return true;
68 }
69
GetButtonName(uint32_t notificationId)70 std::string AudioSafeVolumeNotificationImpl::GetButtonName(uint32_t notificationId)
71 {
72 std::string buttonName;
73
74 switch (notificationId) {
75 case RESTORE_VOLUME_NOTIFICATION_ID:
76 AUDIO_INFO_LOG("GetButtonName RESTORE_VOLUME_NOTIFICATION_ID.");
77 buttonName = GetSystemStringByName(SAFE_VOLUME_RESTORE_VOL_BUTTON_ID);
78 break;
79 case INCREASE_VOLUME_NOTIFICATION_ID:
80 AUDIO_INFO_LOG("GetButtonName INCREASE_VOLUME_NOTIFICATION_ID.");
81 buttonName = GetSystemStringByName(SAFE_VOLUME_INCREASE_VOL_BUTTON_ID);
82 break;
83 default:
84 AUDIO_ERR_LOG("resource name is error.");
85 return buttonName;
86 }
87 return buttonName;
88 }
89
SetActionButton(int32_t notificationId,const std::string & buttonName,Notification::NotificationRequest & request)90 static void SetActionButton(int32_t notificationId, const std::string& buttonName,
91 Notification::NotificationRequest& request)
92 {
93 auto want = std::make_shared<AAFwk::Want>();
94 if (notificationId == RESTORE_VOLUME_NOTIFICATION_ID) {
95 AUDIO_INFO_LOG("SetActionButton AUDIO_RESTORE_VOLUME_EVENT.");
96 want->SetAction(AUDIO_RESTORE_VOLUME_EVENT);
97 } else {
98 AUDIO_INFO_LOG("SetActionButton AUDIO_INCREASE_VOLUME_EVENT.");
99 want->SetAction(AUDIO_INCREASE_VOLUME_EVENT);
100 }
101 std::vector<std::shared_ptr<AAFwk::Want>> wants;
102 wants.push_back(want);
103 std::vector<AbilityRuntime::WantAgent::WantAgentConstant::Flags> flags;
104 flags.push_back(AbilityRuntime::WantAgent::WantAgentConstant::Flags::CONSTANT_FLAG);
105 AbilityRuntime::WantAgent::WantAgentInfo wantAgentInfo(
106 0, AbilityRuntime::WantAgent::WantAgentConstant::OperationType::SEND_COMMON_EVENT,
107 flags, wants, nullptr
108 );
109 auto wantAgentDeal = AbilityRuntime::WantAgent::WantAgentHelper::GetWantAgent(wantAgentInfo);
110 std::shared_ptr<Notification::NotificationActionButton> actionButtonDeal =
111 Notification::NotificationActionButton::Create(nullptr, buttonName, wantAgentDeal);
112 if (actionButtonDeal == nullptr) {
113 AUDIO_ERR_LOG("get notification actionButton nullptr");
114 return;
115 }
116 AUDIO_INFO_LOG("SetActionButton AddActionButton.");
117 request.AddActionButton(actionButtonDeal);
118 }
119
SetExtraParam(int32_t notificationId,Notification::NotificationRequest & request)120 static void SetExtraParam(int32_t notificationId, Notification::NotificationRequest& request)
121 {
122 std::shared_ptr<AAFwk::WantParams> wantParams = std::make_shared<AAFwk::WantParams>();
123 if (notificationId == RESTORE_VOLUME_NOTIFICATION_ID) {
124 AUDIO_INFO_LOG("SetExtraParam AUDIO_RESTORE_VOLUME_EVENT.");
125 wantParams->SetParam(SAVE_VOLUME_SYS_ABILITY_NAME, AAFwk::String::Box(AUDIO_RESTORE_VOLUME_EVENT));
126 } else {
127 AUDIO_INFO_LOG("SetExtraParam AUDIO_INCREASE_VOLUME_EVENT.");
128 wantParams->SetParam(SAVE_VOLUME_SYS_ABILITY_NAME, AAFwk::String::Box(AUDIO_INCREASE_VOLUME_EVENT));
129 }
130
131 request.SetAdditionalData(wantParams);
132 }
133
GetPixelMap()134 bool AudioSafeVolumeNotificationImpl::GetPixelMap()
135 {
136 if (iconPixelMap_ != nullptr) {
137 AUDIO_ERR_LOG("icon pixel map already exists.");
138 return false;
139 }
140
141 std::unique_ptr<uint8_t[]> resourceData;
142 size_t resourceDataLength = 0;
143 auto ret = GetMediaDataByName(SAFE_VOLUME_ICON_ID, resourceDataLength, resourceData);
144 if (ret != Global::Resource::RState::SUCCESS) {
145 AUDIO_ERR_LOG("get (%{public}s) failed, errorCode:%{public}d", SAFE_VOLUME_ICON_ID.c_str(),
146 static_cast<int32_t>(ret));
147 return false;
148 }
149
150 Media::SourceOptions opts;
151 uint32_t errorCode = 0;
152 std::unique_ptr<Media::ImageSource> imageSource =
153 Media::ImageSource::CreateImageSource(resourceData.get(), resourceDataLength, opts, errorCode);
154 Media::DecodeOptions decodeOpts;
155 decodeOpts.desiredSize = {ICON_WIDTH, ICON_HEIGHT};
156 decodeOpts.desiredPixelFormat = Media::PixelFormat::BGRA_8888;
157 if (imageSource) {
158 AUDIO_INFO_LOG("GetPixelMap SUCCESS.");
159 auto pixelMapPtr = imageSource->CreatePixelMap(decodeOpts, errorCode);
160 iconPixelMap_ = std::shared_ptr<Media::PixelMap>(pixelMapPtr.release());
161 }
162 if (errorCode != 0 || (iconPixelMap_ == nullptr)) {
163 AUDIO_ERR_LOG("get badge failed, errorCode:%{public}u", errorCode);
164 return false;
165 }
166 return true;
167 }
168
SetBasicOption(int32_t notificationId,Notification::NotificationRequest & request)169 static void SetBasicOption(int32_t notificationId, Notification::NotificationRequest &request)
170 {
171 request.SetCreatorUid(SAVE_VOLUME_SYS_ABILITY_ID);
172 Notification::NotificationBundleOption bundle(SAVE_VOLUME_SYS_ABILITY_NAME, SAVE_VOLUME_SYS_ABILITY_ID);
173 Notification::NotificationHelper::SetNotificationSlotFlagsAsBundle(bundle, NOTIFICATION_BANNER_FLAG);
174 int32_t userId;
175 AccountSA::OsAccountManager::GetOsAccountLocalIdFromUid(SAVE_VOLUME_SYS_ABILITY_ID, userId);
176 request.SetCreatorUserId(userId);
177 request.SetCreatorPid(getpid());
178 request.SetAutoDeletedTime(OHOS::Notification::NotificationConstant::INVALID_AUTO_DELETE_TIME);
179 request.SetTapDismissed(false);
180 request.SetSlotType(OHOS::Notification::NotificationConstant::SlotType::SOCIAL_COMMUNICATION);
181 if (notificationId == RESTORE_VOLUME_NOTIFICATION_ID) {
182 request.SetNotificationControlFlags(NOTIFICATION_BANNER_FLAG);
183 } else {
184 request.SetNotificationControlFlags(NOTIFICATION_BANNER_FLAG | NOTIFICATION_CLOSE_SOUND_FLAG);
185 }
186 }
187
PublishSafeVolumeNotification(int32_t notificationId)188 void AudioSafeVolumeNotificationImpl::PublishSafeVolumeNotification(int32_t notificationId)
189 {
190 std::shared_ptr<Notification::NotificationNormalContent> normalContent =
191 std::make_shared<Notification::NotificationNormalContent>();
192 if (normalContent == nullptr) {
193 AUDIO_ERR_LOG("get notification normal content nullptr");
194 return;
195 }
196
197 if (!SetTitleAndText(notificationId, normalContent)) {
198 AUDIO_ERR_LOG("error setting title and text");
199 return;
200 }
201
202 std::shared_ptr<Notification::NotificationContent> content =
203 std::make_shared<Notification::NotificationContent>(normalContent);
204
205 if (content == nullptr) {
206 AUDIO_ERR_LOG("get notification content nullptr");
207 return;
208 }
209
210 Notification::NotificationRequest request;
211 SetBasicOption(notificationId, request);
212 request.SetContent(content);
213 request.SetNotificationId(notificationId);
214 GetPixelMap();
215 if (iconPixelMap_ != nullptr) {
216 request.SetLittleIcon(iconPixelMap_);
217 request.SetBadgeIconStyle(Notification::NotificationRequest::BadgeStyle::LITTLE);
218 }
219
220 std::string buttonName = GetButtonName(notificationId);
221 if (!buttonName.empty()) {
222 SetActionButton(notificationId, buttonName, request);
223 }
224
225 SetExtraParam(notificationId, request);
226
227 auto ret = Notification::NotificationHelper::PublishNotification(request);
228 AUDIO_INFO_LOG("safe volume service publish notification result = %{public}d", ret);
229 }
230
CancelSafeVolumeNotification(int32_t notificationId)231 void AudioSafeVolumeNotificationImpl::CancelSafeVolumeNotification(int32_t notificationId)
232 {
233 auto ret = Notification::NotificationHelper::CancelNotification(notificationId);
234 AUDIO_INFO_LOG("safe volume service cancel notification result = %{public}d", ret);
235
236 std::string identity = IPCSkeleton::ResetCallingIdentity();
237 ResourceManagerAdapter::GetInstance()->ReleaseSystemResourceManager();
238 IPCSkeleton::SetCallingIdentity(identity);
239 }
240
GetMediaDataByName(const std::string & name,size_t & len,std::unique_ptr<uint8_t[]> & outValue,uint32_t density)241 Global::Resource::RState AudioSafeVolumeNotificationImpl::GetMediaDataByName(const std::string& name, size_t& len,
242 std::unique_ptr<uint8_t[]>& outValue, uint32_t density)
243 {
244 std::string identity = IPCSkeleton::ResetCallingIdentity();
245 Global::Resource::RState rstate =
246 ResourceManagerAdapter::GetInstance()->GetMediaDataByName(name, len, outValue, density);
247 IPCSkeleton::SetCallingIdentity(identity);
248 return rstate;
249 }
250 } // namespace AudioStandard
251 } // namespace OHOS
252