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