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