1 /*
2 * Copyright (c) 2025-2025 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 "camera_beauty_notification.h"
17
18 namespace OHOS {
19 namespace CameraStandard {
20
21 sptr<CameraBeautyNotification> CameraBeautyNotification::instance_ = nullptr;
22 std::mutex CameraBeautyNotification::instanceMutex_;
23 static constexpr int32_t CAMERA_UID = 1047;
24 const int BEAUTY_NOTIFICATION_ID = 1047001;
25 const std::string BEAUTY_NOTIFICATION_TITLE = "title_adjust_beauty";
26 const std::string BEAUTY_NOTIFICATION_CONTENT_ON = "summary_closed_beauty";
27 const std::string BEAUTY_NOTIFICATION_CONTENT_OFF = "summary_opened_beauty";
28 const std::string BEAUTY_NOTIFICATION_BUTTON_ON = "open_beauty";
29 const std::string BEAUTY_NOTIFICATION_BUTTON_OFF = "close_beauty";
30 const uint32_t BEAUTY_NOTIFICATION_CONTROL_FLAG = 1 << 9;
31 const uint32_t BEAUTY_NOTIFICATION_LOCKSCREEN_FLAG = 1 << 1;
32 const uint32_t BEAUTY_NOTIFICATION_CLOSE_VIBRATION_FLAG = 1 << 4;
33 const std::string BEAUTY_NOTIFICATION_ICON_NAME = "ic_public_camera_beauty";
34 const std::string BEAUTY_NOTIFICATION_GROUP_NAME = "camera_beauty";
35 const int32_t ICON_WIDTH = 220;
36 const int32_t ICON_HEIGHT = 220;
37 const int32_t CONTROL_FLAG_LIMIT = 3;
38
CameraBeautyNotification()39 CameraBeautyNotification::CameraBeautyNotification()
40 {
41 InitBeautyStatus();
42 }
43
~CameraBeautyNotification()44 CameraBeautyNotification::~CameraBeautyNotification()
45 {}
46
GetInstance()47 sptr<CameraBeautyNotification> CameraBeautyNotification::GetInstance()
48 {
49 if (instance_ != nullptr) {
50 return instance_;
51 }
52 std::lock_guard<std::mutex> lock(instanceMutex_);
53 if (instance_ != nullptr) {
54 return instance_;
55 }
56 instance_ = new (std::nothrow) CameraBeautyNotification();
57 return instance_;
58 }
59
PublishNotification(bool isRecordTimes)60 void CameraBeautyNotification::PublishNotification(bool isRecordTimes)
61 {
62 std::lock_guard<std::mutex> lock(notificationMutex_);
63 int32_t beautyStatus = GetBeautyStatus();
64 int32_t beautyTimes = GetBeautyTimes();
65 std::shared_ptr<Notification::NotificationContent> content =
66 std::make_shared<Notification::NotificationContent>(CreateNotificationNormalContent(beautyStatus));
67
68 if (content == nullptr) {
69 MEDIA_ERR_LOG("Create notification content failed");
70 return;
71 }
72
73 Notification::NotificationRequest request;
74 request.SetCreatorUid(CAMERA_UID);
75 request.SetCreatorPid(getpid());
76
77 int32_t userId;
78 AccountSA::OsAccountManager::GetOsAccountLocalIdFromUid(CAMERA_UID, userId);
79
80 request.SetCreatorUserId(userId);
81 request.SetDeliveryTime(GetTimestamp());
82 request.SetAutoDeletedTime(OHOS::Notification::NotificationConstant::INVALID_AUTO_DELETE_TIME);
83 request.SetTapDismissed(false);
84 request.SetSlotType(OHOS::Notification::NotificationConstant::SlotType::SOCIAL_COMMUNICATION);
85 request.SetNotificationId(BEAUTY_NOTIFICATION_ID);
86 request.SetGroupName(BEAUTY_NOTIFICATION_GROUP_NAME);
87 uint32_t baseFlag = BEAUTY_NOTIFICATION_CLOSE_VIBRATION_FLAG | BEAUTY_NOTIFICATION_LOCKSCREEN_FLAG;
88
89 bool isBanner = beautyTimes < CONTROL_FLAG_LIMIT;
90 if (isBanner) {
91 request.SetNotificationControlFlags(baseFlag|BEAUTY_NOTIFICATION_CONTROL_FLAG);
92 } else {
93 request.SetNotificationControlFlags(baseFlag);
94 }
95 request.SetContent(content);
96
97 GetPixelMap();
98 if (iconPixelMap_ != nullptr) {
99 request.SetLittleIcon(iconPixelMap_);
100 request.SetBadgeIconStyle(Notification::NotificationRequest::BadgeStyle::LITTLE);
101 }
102
103 std::string buttonName = beautyStatus == BEAUTY_STATUS_OFF ? GetSystemStringByName(BEAUTY_NOTIFICATION_BUTTON_ON) :
104 GetSystemStringByName(BEAUTY_NOTIFICATION_BUTTON_OFF);
105 SetActionButton(buttonName, request, beautyStatus);
106 int ret = Notification::NotificationHelper::PublishNotification(request);
107 MEDIA_INFO_LOG("CameraBeautyNotification::PublishNotification result = %{public}d", ret);
108 if (ret == CAMERA_OK && isBanner && beautyTimes <= CONTROL_FLAG_LIMIT && isRecordTimes) {
109 beautyTimes_.operator++();
110 SetBeautyTimesFromDataShareHelper(GetBeautyTimes());
111 }
112 }
113
CancelNotification()114 void CameraBeautyNotification::CancelNotification()
115 {
116 std::lock_guard<std::mutex> lock(notificationMutex_);
117 int ret = Notification::NotificationHelper::CancelNotification(BEAUTY_NOTIFICATION_ID);
118 MEDIA_INFO_LOG("CameraBeautyNotification::CancelNotification result = %{public}d", ret);
119 }
120
SetBeautyStatus(int32_t beautyStatus)121 void CameraBeautyNotification::SetBeautyStatus(int32_t beautyStatus)
122 {
123 beautyStatus_.store(beautyStatus);
124 }
125
GetBeautyStatus()126 int32_t CameraBeautyNotification::GetBeautyStatus()
127 {
128 return beautyStatus_.load();
129 }
130
SetBeautyTimes(int32_t beautyTimes)131 void CameraBeautyNotification::SetBeautyTimes(int32_t beautyTimes)
132 {
133 beautyTimes_.store(beautyTimes);
134 }
135
GetBeautyTimes()136 int32_t CameraBeautyNotification::GetBeautyTimes()
137 {
138 return beautyTimes_.load();
139 }
140
GetBeautyStatusFromDataShareHelper(int32_t & beautyStatus)141 int32_t CameraBeautyNotification::GetBeautyStatusFromDataShareHelper(int32_t &beautyStatus)
142 {
143 if (cameraDataShareHelper_ == nullptr) {
144 cameraDataShareHelper_ = std::make_shared<CameraDataShareHelper>();
145 }
146 std::string value = "";
147 auto ret = cameraDataShareHelper_->QueryOnce(PREDICATES_CAMERA_BEAUTY_STATUS, value);
148 if (ret != CAMERA_OK) {
149 beautyStatus = BEAUTY_STATUS_OFF;
150 } else {
151 beautyStatus = std::stoi(value);
152 }
153 return CAMERA_OK;
154 }
155
SetBeautyStatusFromDataShareHelper(int32_t beautyStatus)156 int32_t CameraBeautyNotification::SetBeautyStatusFromDataShareHelper(int32_t beautyStatus)
157 {
158 if (cameraDataShareHelper_ == nullptr) {
159 cameraDataShareHelper_ = std::make_shared<CameraDataShareHelper>();
160 }
161 auto ret = cameraDataShareHelper_->UpdateOnce(PREDICATES_CAMERA_BEAUTY_STATUS, std::to_string(beautyStatus));
162 CHECK_ERROR_RETURN_RET_LOG(ret != CAMERA_OK, CAMERA_ALLOC_ERROR,
163 "SetBeautyStatusFromDataShareHelper UpdateOnce fail.");
164 return CAMERA_OK;
165 }
166
GetBeautyTimesFromDataShareHelper(int32_t & times)167 int32_t CameraBeautyNotification::GetBeautyTimesFromDataShareHelper(int32_t ×)
168 {
169 if (cameraDataShareHelper_ == nullptr) {
170 cameraDataShareHelper_ = std::make_shared<CameraDataShareHelper>();
171 }
172 std::string value = "";
173 auto ret = cameraDataShareHelper_->QueryOnce(PREDICATES_CAMERA_BEAUTY_TIMES, value);
174 if (ret != CAMERA_OK) {
175 times = 0;
176 } else {
177 times = std::stoi(value);
178 }
179 return CAMERA_OK;
180 }
181
SetBeautyTimesFromDataShareHelper(int32_t times)182 int32_t CameraBeautyNotification::SetBeautyTimesFromDataShareHelper(int32_t times)
183 {
184 if (cameraDataShareHelper_ == nullptr) {
185 cameraDataShareHelper_ = std::make_shared<CameraDataShareHelper>();
186 }
187 auto ret = cameraDataShareHelper_->UpdateOnce(PREDICATES_CAMERA_BEAUTY_TIMES, std::to_string(times));
188 CHECK_ERROR_RETURN_RET_LOG(ret != CAMERA_OK, CAMERA_ALLOC_ERROR,
189 "SetBeautyTimesFromDataShareHelper UpdateOnce fail.");
190 return CAMERA_OK;
191 }
192
InitBeautyStatus()193 void CameraBeautyNotification::InitBeautyStatus()
194 {
195 int32_t beautyStatus = BEAUTY_STATUS_OFF;
196 int32_t times = 0;
197 GetBeautyStatusFromDataShareHelper(beautyStatus);
198 GetBeautyTimesFromDataShareHelper(times);
199 MEDIA_INFO_LOG("InitBeautyStatus beautyStatus = %{public}d, times = %{public}d", beautyStatus, times);
200 SetBeautyStatus(beautyStatus);
201 SetBeautyTimes(times);
202 }
203
CreateNotificationNormalContent(int32_t beautyStatus)204 std::shared_ptr<Notification::NotificationNormalContent> CameraBeautyNotification::CreateNotificationNormalContent(
205 int32_t beautyStatus)
206 {
207 std::shared_ptr<Notification::NotificationNormalContent> normalContent =
208 std::make_shared<Notification::NotificationNormalContent>();
209 CHECK_ERROR_RETURN_RET_LOG(normalContent == nullptr, nullptr, "Create normalContent failed");
210 normalContent->SetTitle(GetSystemStringByName(BEAUTY_NOTIFICATION_TITLE));
211 normalContent->SetText(beautyStatus == BEAUTY_STATUS_OFF ? GetSystemStringByName(BEAUTY_NOTIFICATION_CONTENT_ON) :
212 GetSystemStringByName(BEAUTY_NOTIFICATION_CONTENT_OFF));
213 return normalContent;
214 }
215
SetActionButton(const std::string & buttonName,Notification::NotificationRequest & request,int32_t beautyStatus)216 void CameraBeautyNotification::SetActionButton(const std::string& buttonName,
217 Notification::NotificationRequest& request, int32_t beautyStatus)
218 {
219 auto want = std::make_shared<AAFwk::Want>();
220 want->SetAction(EVENT_CAMERA_BEAUTY_NOTIFICATION);
221
222 std::shared_ptr<OHOS::AAFwk::WantParams> wantParams = std::make_shared<OHOS::AAFwk::WantParams>();
223 sptr<OHOS::AAFwk::IInterface> intIt = OHOS::AAFwk::Integer::Box(beautyStatus);
224 wantParams->SetParam(BEAUTY_NOTIFICATION_ACTION_PARAM, intIt);
225
226 want->SetParams(*wantParams);
227 std::vector<std::shared_ptr<AAFwk::Want>> wants;
228 wants.push_back(want);
229
230 std::vector<AbilityRuntime::WantAgent::WantAgentConstant::Flags> flags;
231 flags.push_back(AbilityRuntime::WantAgent::WantAgentConstant::Flags::CONSTANT_FLAG);
232
233 AbilityRuntime::WantAgent::WantAgentInfo wantAgentInfo(
234 0, AbilityRuntime::WantAgent::WantAgentConstant::OperationType::SEND_COMMON_EVENT,
235 flags, wants, wantParams
236 );
237 auto wantAgentDeal = AbilityRuntime::WantAgent::WantAgentHelper::GetWantAgent(wantAgentInfo);
238 std::shared_ptr<Notification::NotificationActionButton> actionButtonDeal =
239 Notification::NotificationActionButton::Create(nullptr, buttonName, wantAgentDeal);
240 if (actionButtonDeal == nullptr) {
241 MEDIA_INFO_LOG("Create actionButtonDeal failed");
242 return;
243 }
244 request.AddActionButton(actionButtonDeal);
245 }
246
GetSystemStringByName(std::string name)247 std::string CameraBeautyNotification::GetSystemStringByName(std::string name)
248 {
249 InitResourceManager();
250 std::string result;
251 std::string identity = IPCSkeleton::ResetCallingIdentity();
252 resourceManager_->GetStringByName(name.c_str(), result);
253 IPCSkeleton::SetCallingIdentity(identity);
254 MEDIA_DEBUG_LOG("name: %{public}s, result: %{public}s", name.c_str(), result.c_str());
255 return result;
256 }
257
GetPixelMap()258 void CameraBeautyNotification::GetPixelMap()
259 {
260 if (iconPixelMap_ != nullptr) {
261 MEDIA_ERR_LOG("Pixel map already exists.");
262 return;
263 }
264
265 size_t len = 0;
266 std::unique_ptr<uint8_t[]> data;
267 Global::Resource::RState rstate = GetMediaDataByName(BEAUTY_NOTIFICATION_ICON_NAME.c_str(), len, data);
268 if (rstate != Global::Resource::RState::SUCCESS) {
269 MEDIA_ERR_LOG("GetMediaDataByName failed");
270 return;
271 }
272
273 OHOS::Media::SourceOptions opts;
274 uint32_t errorCode = 0;
275 std::unique_ptr<OHOS::Media::ImageSource> imageSource =
276 OHOS::Media::ImageSource::CreateImageSource(data.get(), len, opts, errorCode);
277 MEDIA_INFO_LOG("CreateImageSource errorCode: %{public}d", static_cast<int32_t>(errorCode));
278 if (imageSource == nullptr) {
279 MEDIA_ERR_LOG("imageSource is nullptr");
280 return;
281 }
282 OHOS::Media::DecodeOptions decodeOpts;
283 decodeOpts.desiredSize = {ICON_WIDTH, ICON_HEIGHT};
284 decodeOpts.desiredPixelFormat = OHOS::Media::PixelFormat::BGRA_8888;
285 std::unique_ptr<OHOS::Media::PixelMap> pixelMap = imageSource->CreatePixelMap(decodeOpts, errorCode);
286 MEDIA_INFO_LOG("CreatePixelMap errorCode: %{public}d", static_cast<int32_t>(errorCode));
287 if (pixelMap == nullptr) {
288 MEDIA_ERR_LOG("pixelMap is nullptr");
289 return;
290 }
291 iconPixelMap_ = std::move(pixelMap);
292 }
293
GetMediaDataByName(std::string name,size_t & len,std::unique_ptr<uint8_t[]> & outValue,uint32_t density)294 Global::Resource::RState CameraBeautyNotification::GetMediaDataByName(std::string name, size_t& len,
295 std::unique_ptr<uint8_t[]> &outValue, uint32_t density)
296 {
297 InitResourceManager();
298 std::string identity = IPCSkeleton::ResetCallingIdentity();
299 Global::Resource::RState rstate = resourceManager_->GetMediaDataByName(name.c_str(), len, outValue);
300 IPCSkeleton::SetCallingIdentity(identity);
301 MEDIA_INFO_LOG("rstate: %{public}d", static_cast<int32_t>(rstate));
302 return rstate;
303 }
304
InitResourceManager()305 void CameraBeautyNotification::InitResourceManager()
306 {
307 if (!resourceManager_) {
308 MEDIA_INFO_LOG("Init");
309 resourceManager_ = Global::Resource::GetSystemResourceManagerNoSandBox();
310 }
311 if (!resConfig_) {
312 resConfig_ = Global::Resource::CreateResConfig();
313 }
314 RefreshResConfig();
315 }
316
RefreshResConfig()317 void CameraBeautyNotification::RefreshResConfig()
318 {
319 std::string language = Global::I18n::LocaleConfig::GetSystemLanguage();
320 if (language.empty()) {
321 MEDIA_INFO_LOG("Get system language failed, skip RefreshResConfig");
322 return;
323 }
324 UErrorCode status = U_ZERO_ERROR;
325 icu::Locale locale = icu::Locale::forLanguageTag(language, status);
326 if (status != U_ZERO_ERROR || locale == nullptr) {
327 MEDIA_INFO_LOG("forLanguageTag failed, errCode:%{public}d", status);
328 return;
329 }
330 if (!resConfig_) {
331 MEDIA_INFO_LOG("resConfig_ is nullptr");
332 return;
333 }
334 resConfig_->SetLocaleInfo(locale.getLanguage(), locale.getScript(), locale.getCountry());
335 if (!resourceManager_) {
336 MEDIA_INFO_LOG("resourceManager_ is nullptr");
337 return;
338 }
339 resourceManager_->UpdateResConfig(*resConfig_);
340 MEDIA_INFO_LOG("Refresh success");
341 }
342 } // namespace CameraStandard
343 } // namespace OHOS
344