1 /*
2 * Copyright (c) 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 #include "sts_subscribe.h"
16
17 #include "ans_log_wrapper.h"
18 #include "notification_helper.h"
19 #include "sts_throw_erro.h"
20 #include "sts_common.h"
21 #include "sts_sorting_map.h"
22 #include "sts_subscribe_info.h"
23 #include "ani_common_util.h"
24
25 namespace OHOS {
26 namespace NotificationSts {
StsDistributedOperationCallback(ani_object promise,ani_resolver resolver)27 StsDistributedOperationCallback::StsDistributedOperationCallback(ani_object promise, ani_resolver resolver)
28 : resolver_(resolver)
29 {
30 }
31
OnOperationCallback(const int32_t operationResult)32 ErrCode StsDistributedOperationCallback::OnOperationCallback(const int32_t operationResult)
33 {
34 std::lock_guard<std::mutex> l(lock_);
35 if (isCall_) {
36 return ERR_OK;
37 }
38 if (etsVm_ == nullptr) {
39 ANS_LOGD("etsVm_ is null");
40 return ANI_ERROR;
41 }
42 ani_env* etsEnv;
43 ani_status aniResult = ANI_ERROR;
44 ani_options aniArgs { 0, nullptr };
45 aniResult = etsVm_->AttachCurrentThread(&aniArgs, ANI_VERSION_1, &etsEnv);
46 if (aniResult != ANI_OK) {
47 ANS_LOGD("StsDistributedOperationCallback AttachCurrentThread error. result: %{public}d.", aniResult);
48 return aniResult;
49 }
50 OnStsOperationCallback(etsEnv, operationResult);
51 aniResult = etsVm_->DetachCurrentThread();
52 if (aniResult != ANI_OK) {
53 ANS_LOGD("StsDistributedOperationCallback DetachCurrentThread error. result: %{public}d.", aniResult);
54 return aniResult;
55 }
56 isCall_ = true;
57 return ERR_OK;
58 }
59
OnStsOperationCallback(ani_env * env,const int32_t operationResult)60 void StsDistributedOperationCallback::OnStsOperationCallback(ani_env *env, const int32_t operationResult)
61 {
62 ANS_LOGD("ENTER");
63 if (env == nullptr) {
64 ANS_LOGD("env is nullptr");
65 return;
66 }
67 ani_status status = ANI_OK;
68 int32_t externalErrorCode = (operationResult == ERR_OK) ? operationResult : GetExternalCode(operationResult);
69 ANS_LOGD("operationResult %{public}d, externalCode %{public}d", operationResult, externalErrorCode);
70
71 if (externalErrorCode == ERR_OK) {
72 ANS_LOGD("OnStsOperationCallback Resolve");
73 ani_object ret = OHOS::AppExecFwk::CreateInt(env, externalErrorCode);
74 if (ANI_OK != (status = env->PromiseResolver_Resolve(resolver_, static_cast<ani_ref>(ret)))) {
75 ANS_LOGD("PromiseResolver_Resolve faild. status %{public}d", status);
76 return;
77 }
78 } else {
79 ANS_LOGD("OnStsOperationCallback reject");
80 std::string errMsg = FindAnsErrMsg(externalErrorCode);
81 ani_error rejection =
82 static_cast<ani_error>(OHOS::AbilityRuntime::EtsErrorUtil::CreateError(env, externalErrorCode, errMsg));
83 if (ANI_OK != (status = env->PromiseResolver_Reject(resolver_, rejection))) {
84 ANS_LOGD("PromiseResolver_Resolve faild. status %{public}d", status);
85 }
86 }
87 }
88
SetVm(ani_vm * vm)89 void StsDistributedOperationCallback::SetVm(ani_vm *vm)
90 {
91 etsVm_ = vm;
92 }
93
StsSubscriberInstance()94 StsSubscriberInstance::StsSubscriberInstance()
95 {}
~StsSubscriberInstance()96 StsSubscriberInstance::~StsSubscriberInstance()
97 {}
OnCanceled(const std::shared_ptr<OHOS::Notification::Notification> & request,const std::shared_ptr<NotificationSortingMap> & sortingMap,int32_t deleteReason)98 void StsSubscriberInstance::OnCanceled(
99 const std::shared_ptr<OHOS::Notification::Notification> &request,
100 const std::shared_ptr<NotificationSortingMap> &sortingMap,
101 int32_t deleteReason)
102 {
103 ANS_LOGD("enter");
104 std::lock_guard<std::mutex> l(lock_);
105 ani_env* etsEnv;
106 ani_status aniResult = ANI_ERROR;
107 ani_options aniArgs { 0, nullptr };
108 aniResult = vm_->AttachCurrentThread(&aniArgs, ANI_VERSION_1, &etsEnv);
109 if (aniResult != ANI_OK) {
110 ANS_LOGD("AttachCurrentThread error. result: %{public}d.", aniResult);
111 return;
112 }
113 std::vector<ani_ref> vec;
114 ani_object obj;
115 if (WarpSubscribeCallbackData(etsEnv, request, sortingMap, deleteReason, obj)) {
116 vec.push_back(obj);
117 CallFunction(etsEnv, "onCancel", vec);
118 } else {
119 ANS_LOGD("WarpSubscribeCallbackData faild");
120 }
121 aniResult = vm_->DetachCurrentThread();
122 if (aniResult != ANI_OK) {
123 ANS_LOGD("DetachCurrentThread error. result: %{public}d.", aniResult);
124 return;
125 }
126 ANS_LOGD("done");
127 }
OnConsumed(const std::shared_ptr<OHOS::Notification::Notification> & request,const std::shared_ptr<NotificationSortingMap> & sortingMap)128 void StsSubscriberInstance::OnConsumed(
129 const std::shared_ptr<OHOS::Notification::Notification> &request,
130 const std::shared_ptr<NotificationSortingMap> &sortingMap)
131 {
132 ANS_LOGD("enter");
133 std::lock_guard<std::mutex> l(lock_);
134 ani_env* etsEnv;
135 ani_status aniResult = ANI_ERROR;
136 ani_options aniArgs { 0, nullptr };
137 aniResult = vm_->AttachCurrentThread(&aniArgs, ANI_VERSION_1, &etsEnv);
138 if (aniResult != ANI_OK) {
139 ANS_LOGD("AttachCurrentThread error. result: %{public}d.", aniResult);
140 return;
141 }
142 std::vector<ani_ref> vec;
143 ani_object obj;
144 if (WarpSubscribeCallbackData(etsEnv, request, sortingMap, -1, obj)) {
145 vec.push_back(obj);
146 CallFunction(etsEnv, "onConsume", vec);
147 } else {
148 ANS_LOGD("WarpSubscribeCallbackData faild");
149 }
150 aniResult = vm_->DetachCurrentThread();
151 if (aniResult != ANI_OK) {
152 ANS_LOGD("DetachCurrentThread error. result: %{public}d.", aniResult);
153 return;
154 }
155 ANS_LOGD("done");
156 }
OnUpdate(const std::shared_ptr<NotificationSortingMap> & sortingMap)157 void StsSubscriberInstance::OnUpdate(const std::shared_ptr<NotificationSortingMap> &sortingMap)
158 {
159 ANS_LOGD("enter");
160 std::lock_guard<std::mutex> l(lock_);
161 ani_env* etsEnv;
162 ani_status aniResult = ANI_ERROR;
163 ani_options aniArgs { 0, nullptr };
164 aniResult = vm_->AttachCurrentThread(&aniArgs, ANI_VERSION_1, &etsEnv);
165 if (aniResult != ANI_OK) {
166 ANS_LOGD("AttachCurrentThread error. result: %{public}d.", aniResult);
167 return;
168 }
169 std::vector<ani_ref> vec;
170 ani_object obj;
171 if (WarpNotificationSortingMap(etsEnv, sortingMap, obj)) {
172 vec.push_back(obj);
173 CallFunction(etsEnv, "onUpdate", vec);
174 } else {
175 ANS_LOGD("WarpNotificationSortingMap faild");
176 }
177 aniResult = vm_->DetachCurrentThread();
178 if (aniResult != ANI_OK) {
179 ANS_LOGD("DetachCurrentThread error. result: %{public}d.", aniResult);
180 return;
181 }
182 ANS_LOGD("done");
183 }
OnConnected()184 void StsSubscriberInstance::OnConnected()
185 {
186 ANS_LOGD("enter");
187 std::lock_guard<std::mutex> l(lock_);
188 ani_env* etsEnv;
189 ani_status aniResult = ANI_ERROR;
190 ani_options aniArgs { 0, nullptr };
191 aniResult = vm_->AttachCurrentThread(&aniArgs, ANI_VERSION_1, &etsEnv);
192 if (aniResult != ANI_OK) {
193 ANS_LOGD("AttachCurrentThread error. result: %{public}d.", aniResult);
194 return;
195 }
196 std::vector<ani_ref> vec;
197 CallFunction(etsEnv, "onConnect", vec);
198 aniResult = vm_->DetachCurrentThread();
199 if (aniResult != ANI_OK) {
200 ANS_LOGD("DetachCurrentThread error. result: %{public}d.", aniResult);
201 return;
202 }
203 ANS_LOGD("done");
204 }
OnDisconnected()205 void StsSubscriberInstance::OnDisconnected()
206 {
207 ANS_LOGD("enter");
208 std::lock_guard<std::mutex> l(lock_);
209 ani_env* etsEnv;
210 ani_status aniResult = ANI_ERROR;
211 ani_options aniArgs { 0, nullptr };
212 aniResult = vm_->AttachCurrentThread(&aniArgs, ANI_VERSION_1, &etsEnv);
213 if (aniResult != ANI_OK) {
214 ANS_LOGD("AttachCurrentThread error. result: %{public}d.", aniResult);
215 return;
216 }
217 std::vector<ani_ref> vec;
218 CallFunction(etsEnv, "onDisconnect", vec);
219 if (!SubscriberInstanceManager::GetInstance()->DelSubscriberInstancesInfo(etsEnv, obj_)) {
220 ANS_LOGD("DelSubscriberInstancesInfo faild");
221 } else {
222 ANS_LOGD("DelSubscriberInstancesInfo suc..");
223 }
224 aniResult = vm_->DetachCurrentThread();
225 if (aniResult != ANI_OK) {
226 ANS_LOGD("DetachCurrentThread error. result: %{public}d.", aniResult);
227 return;
228 }
229 ANS_LOGD("done");
230 }
OnDied()231 void StsSubscriberInstance::OnDied()
232 {
233 ANS_LOGD("enter");
234 std::lock_guard<std::mutex> l(lock_);
235 ani_env* etsEnv;
236 ani_status aniResult = ANI_ERROR;
237 ani_options aniArgs { 0, nullptr };
238 aniResult = vm_->AttachCurrentThread(&aniArgs, ANI_VERSION_1, &etsEnv);
239 if (aniResult != ANI_OK) {
240 ANS_LOGD("AttachCurrentThread error. result: %{public}d.", aniResult);
241 return;
242 }
243 std::vector<ani_ref> vec;
244 CallFunction(etsEnv, "onDestroy", vec);
245 aniResult = vm_->DetachCurrentThread();
246 if (aniResult != ANI_OK) {
247 ANS_LOGD("DetachCurrentThread error. result: %{public}d.", aniResult);
248 return;
249 }
250 ANS_LOGD("done");
251 }
OnDoNotDisturbDateChange(const std::shared_ptr<NotificationDoNotDisturbDate> & date)252 void StsSubscriberInstance::OnDoNotDisturbDateChange(const std::shared_ptr<NotificationDoNotDisturbDate> &date)
253 {
254 ANS_LOGD("enter");
255 std::lock_guard<std::mutex> l(lock_);
256 }
onDoNotDisturbChanged(const std::shared_ptr<NotificationDoNotDisturbDate> & date)257 void StsSubscriberInstance::onDoNotDisturbChanged(const std::shared_ptr<NotificationDoNotDisturbDate> &date)
258 {
259 ANS_LOGD("enter");
260 std::lock_guard<std::mutex> l(lock_);
261 ani_env* etsEnv;
262 ani_status aniResult = ANI_ERROR;
263 ani_options aniArgs { 0, nullptr };
264 aniResult = vm_->AttachCurrentThread(&aniArgs, ANI_VERSION_1, &etsEnv);
265 if (aniResult != ANI_OK) {
266 ANS_LOGD("AttachCurrentThread error. result: %{public}d.", aniResult);
267 return;
268 }
269 std::vector<ani_ref> vec;
270 ani_object obj;
271 if (WarpNotificationDoNotDisturbDate(etsEnv, date, obj)) {
272 vec.push_back(obj);
273 CallFunction(etsEnv, "onDoNotDisturbChanged", vec);
274 } else {
275 ANS_LOGD("WarpNotificationDoNotDisturbDate faild");
276 }
277 aniResult = vm_->DetachCurrentThread();
278 if (aniResult != ANI_OK) {
279 ANS_LOGD("DetachCurrentThread error. result: %{public}d.", aniResult);
280 return;
281 }
282 ANS_LOGD("done");
283 }
OnEnabledNotificationChanged(const std::shared_ptr<EnabledNotificationCallbackData> & callbackData)284 void StsSubscriberInstance::OnEnabledNotificationChanged(
285 const std::shared_ptr<EnabledNotificationCallbackData> &callbackData)
286 {
287 ANS_LOGD("enter");
288 std::lock_guard<std::mutex> l(lock_);
289 ani_env* etsEnv;
290 ani_status aniResult = ANI_ERROR;
291 ani_options aniArgs { 0, nullptr };
292 aniResult = vm_->AttachCurrentThread(&aniArgs, ANI_VERSION_1, &etsEnv);
293 if (aniResult != ANI_OK) {
294 ANS_LOGD("AttachCurrentThread error. result: %{public}d.", aniResult);
295 return;
296 }
297 std::vector<ani_ref> vec;
298 ani_object obj;
299 if (WarpEnabledNotificationCallbackData(etsEnv, callbackData, obj)) {
300 vec.push_back(obj);
301 CallFunction(etsEnv, "onEnabledNotificationChanged", vec);
302 } else {
303 ANS_LOGD("WarpEnabledNotificationCallbackData faild");
304 }
305 aniResult = vm_->DetachCurrentThread();
306 if (aniResult != ANI_OK) {
307 ANS_LOGD("DetachCurrentThread error. result: %{public}d.", aniResult);
308 return;
309 }
310 ANS_LOGD("done");
311 }
OnBadgeChanged(const std::shared_ptr<BadgeNumberCallbackData> & badgeData)312 void StsSubscriberInstance::OnBadgeChanged(const std::shared_ptr<BadgeNumberCallbackData> &badgeData)
313 {
314 ANS_LOGD("enter");
315 std::lock_guard<std::mutex> l(lock_);
316 ani_env* etsEnv;
317 ani_status aniResult = ANI_ERROR;
318 ani_options aniArgs { 0, nullptr };
319 aniResult = vm_->AttachCurrentThread(&aniArgs, ANI_VERSION_1, &etsEnv);
320 if (aniResult != ANI_OK) {
321 ANS_LOGD("AttachCurrentThread error. result: %{public}d.", aniResult);
322 return;
323 }
324 std::vector<ani_ref> vec;
325 ani_object obj;
326 if (WarpBadgeNumberCallbackData(etsEnv, badgeData, obj)) {
327 vec.push_back(obj);
328 CallFunction(etsEnv, "onBadgeChanged", vec);
329 } else {
330 ANS_LOGD("WarpBadgeNumberCallbackData faild");
331 }
332 aniResult = vm_->DetachCurrentThread();
333 if (aniResult != ANI_OK) {
334 ANS_LOGD("DetachCurrentThread error. result: %{public}d.", aniResult);
335 return;
336 }
337 ANS_LOGD("done");
338 }
OnBadgeEnabledChanged(const sptr<EnabledNotificationCallbackData> & callbackData)339 void StsSubscriberInstance::OnBadgeEnabledChanged(const sptr<EnabledNotificationCallbackData> &callbackData)
340 {
341 ANS_LOGD("enter");
342 std::lock_guard<std::mutex> l(lock_);
343 ani_env* etsEnv;
344 ani_status aniResult = ANI_ERROR;
345 ani_options aniArgs { 0, nullptr };
346 aniResult = vm_->AttachCurrentThread(&aniArgs, ANI_VERSION_1, &etsEnv);
347 if (aniResult != ANI_OK) {
348 ANS_LOGD("AttachCurrentThread error. result: %{public}d.", aniResult);
349 return;
350 }
351 std::vector<ani_ref> vec;
352 ani_object obj;
353 std::shared_ptr<EnabledNotificationCallbackData> data = std::make_shared<EnabledNotificationCallbackData>();
354 data->SetBundle(callbackData->GetBundle());
355 data->SetUid(callbackData->GetUid());
356 data->SetEnable(callbackData->GetEnable());
357 if (WarpEnabledNotificationCallbackData(etsEnv, data, obj)) {
358 vec.push_back(obj);
359 CallFunction(etsEnv, "onBadgeEnabledChanged", vec);
360 } else {
361 ANS_LOGD("WarpEnabledNotificationCallbackData faild");
362 }
363 aniResult = vm_->DetachCurrentThread();
364 if (aniResult != ANI_OK) {
365 ANS_LOGD("DetachCurrentThread error. result: %{public}d.", aniResult);
366 return;
367 }
368 ANS_LOGD("done");
369 }
OnBatchCanceled(const std::vector<std::shared_ptr<OHOS::Notification::Notification>> & requestList,const std::shared_ptr<NotificationSortingMap> & sortingMap,int32_t deleteReason)370 void StsSubscriberInstance::OnBatchCanceled(
371 const std::vector<std::shared_ptr<OHOS::Notification::Notification>> &requestList,
372 const std::shared_ptr<NotificationSortingMap> &sortingMap, int32_t deleteReason)
373 {
374 ANS_LOGD("enter");
375 std::lock_guard<std::mutex> l(lock_);
376 ani_env* etsEnv;
377 ani_status aniResult = ANI_ERROR;
378 ani_options aniArgs { 0, nullptr };
379 aniResult = vm_->AttachCurrentThread(&aniArgs, ANI_VERSION_1, &etsEnv);
380 if (aniResult != ANI_OK) {
381 ANS_LOGD("AttachCurrentThread error. result: %{public}d.", aniResult);
382 return;
383 }
384 std::vector<ani_ref> vec;
385 ani_object obj;
386 if (WarpSubscribeCallbackDataArray(etsEnv, requestList, sortingMap, deleteReason, obj)) {
387 vec.push_back(obj);
388 CallFunction(etsEnv, "onBatchCancel", vec);
389 } else {
390 ANS_LOGD("WarpSubscribeCallbackDataArray faild");
391 }
392 aniResult = vm_->DetachCurrentThread();
393 if (aniResult != ANI_OK) {
394 ANS_LOGD("DetachCurrentThread error. result: %{public}d.", aniResult);
395 return;
396 }
397 ANS_LOGD("done");
398 }
HasOnBatchCancelCallback()399 bool StsSubscriberInstance::HasOnBatchCancelCallback()
400 {
401 ANS_LOGD("enter");
402 std::lock_guard<std::mutex> l(lock_);
403 ani_env* etsEnv;
404 ani_status aniResult = ANI_ERROR;
405 ani_options aniArgs { 0, nullptr };
406 aniResult = vm_->AttachCurrentThread(&aniArgs, ANI_VERSION_1, &etsEnv);
407 if (aniResult != ANI_OK) {
408 ANS_LOGD("AttachCurrentThread error. result: %{public}d.", aniResult);
409 return false;
410 }
411
412 ani_ref fn_ref;
413 aniResult = etsEnv->Object_GetFieldByName_Ref(static_cast<ani_object>(ref_), "onBatchCancel", &fn_ref);
414 if (ANI_OK != aniResult) {
415 ANS_LOGD("Object_GetFieldByName_Ref 'onBatchCancel' error. result: %{public}d.", aniResult);
416 vm_->DetachCurrentThread();
417 return false;
418 }
419 ani_boolean isUndefined = true;
420 if (ANI_OK != etsEnv->Reference_IsUndefined(fn_ref, &isUndefined)) {
421 ANS_LOGD("Reference_IsUndefined faild");
422 vm_->DetachCurrentThread();
423 return false;
424 }
425 aniResult = vm_->DetachCurrentThread();
426 if (aniResult != ANI_OK) {
427 ANS_LOGD("StsDistributedOperationCallback DetachCurrentThread error. result: %{public}d.", aniResult);
428 }
429 if (isUndefined == ANI_FALSE) {
430 return true;
431 }
432 return false;
433 }
SetObject(ani_env * env,ani_object obj)434 bool StsSubscriberInstance::SetObject(ani_env *env, ani_object obj)
435 {
436 ANS_LOGD("enter");
437 std::lock_guard<std::mutex> l(lock_);
438 if (env == nullptr || obj == nullptr) return false;
439 if (ANI_OK != env->GetVM(&vm_)) {
440 ANS_LOGD("GetVM faild");
441 return false;
442 }
443 if (ANI_OK != env->GlobalReference_Create(obj, &ref_)) {
444 ANS_LOGD("GlobalReference_Create faild");
445 return false;
446 }
447 obj_ = obj;
448 return true;
449 }
IsInit()450 bool StsSubscriberInstance::IsInit()
451 {
452 ANS_LOGD("enter");
453 std::lock_guard<std::mutex> l(lock_);
454 return (ref_ != nullptr && vm_ != nullptr);
455 }
Compare(ani_env * env,ani_object obj)456 bool StsSubscriberInstance::Compare(ani_env *env, ani_object obj)
457 {
458 ANS_LOGD("enter");
459 if (!IsInit()) return false;
460 if (obj == nullptr || env == nullptr) return false;
461 ani_ref ref;
462 if (env->GlobalReference_Create(obj, &ref) != ANI_OK) return false;
463 ani_boolean result = ANI_FALSE;
464 env->Reference_StrictEquals(ref, ref_, &result);
465 env->GlobalReference_Delete(ref);
466 return (result == ANI_TRUE) ? true : false;
467 }
Compare(std::shared_ptr<StsSubscriberInstance> instance)468 bool StsSubscriberInstance::Compare(std::shared_ptr<StsSubscriberInstance> instance)
469 {
470 ANS_LOGD("enter");
471 if (instance == nullptr) return false;
472 if (instance->obj_ == obj_) {
473 ANS_LOGD("Compare is ture");
474 return true;
475 }
476 ANS_LOGD("Compare is false");
477 return false;
478 }
CallFunction(ani_env * env,const char * func,std::vector<ani_ref> & parm)479 bool StsSubscriberInstance::CallFunction(ani_env *env, const char *func, std::vector<ani_ref> &parm)
480 {
481 ANS_LOGD("enter");
482 if (env == nullptr) return false;
483 ani_ref fn_ref;
484 ani_status aniResult = env->Object_GetPropertyByName_Ref(static_cast<ani_object>(ref_), func, &fn_ref);
485 if (ANI_OK != aniResult) {
486 ANS_LOGD("Object_GetPropertyByName_Ref '%{public}s' error. result: %{public}d.", func, aniResult);
487 return false;
488 }
489 ani_boolean IsUndefined = ANI_FALSE;
490 if (ANI_OK != env->Reference_IsUndefined(fn_ref, &IsUndefined) || IsUndefined == ANI_TRUE) {
491 ANS_LOGD("Reference_IsUndefined faild. or IsUndefined");
492 return false;
493 }
494 ani_ref fnReturnVal;
495 aniResult = env->FunctionalObject_Call(
496 static_cast<ani_fn_object>(fn_ref), parm.size(), parm.data(), &fnReturnVal);
497 if (ANI_OK != aniResult) {
498 ANS_LOGD("FunctionalObject_Call error. result: %{public}d.", aniResult);
499 return false;
500 }
501 ANS_LOGD("done");
502 return true;
503 }
504
HasNotificationSubscriber(ani_env * env,ani_object value,std::shared_ptr<StsSubscriberInstance> & subscriberInfo)505 bool SubscriberInstanceManager::HasNotificationSubscriber(
506 ani_env *env, ani_object value, std::shared_ptr<StsSubscriberInstance> &subscriberInfo)
507 {
508 ANS_LOGD("enter");
509 for (auto &iter : subscriberInstances_) {
510 if (iter->Compare(env, value)) {
511 subscriberInfo = iter;
512 return true;
513 }
514 }
515 return false;
516 }
AddSubscriberInstancesInfo(ani_env * env,std::shared_ptr<StsSubscriberInstance> & subscriberInfo)517 bool SubscriberInstanceManager::AddSubscriberInstancesInfo(
518 ani_env *env, std::shared_ptr<StsSubscriberInstance> &subscriberInfo)
519 {
520 ANS_LOGD("enter");
521 if (!subscriberInfo->IsInit()) {
522 ANS_LOGE("subscriberInfo not init");
523 return false;
524 }
525 std::lock_guard<std::mutex> lock(mutex_);
526 subscriberInstances_.emplace_back(subscriberInfo);
527 return true;
528 }
DelSubscriberInstancesInfo(ani_env * env,ani_object obj)529 bool SubscriberInstanceManager::DelSubscriberInstancesInfo(
530 ani_env *env, ani_object obj)
531 {
532 ANS_LOGD("enter");
533 if (obj == nullptr) {
534 ANS_LOGE("obj is null");
535 return false;
536 }
537 std::lock_guard<std::mutex> lock(mutex_);
538 for (auto it = subscriberInstances_.begin(); it != subscriberInstances_.end(); ++it) {
539 if ((*it)->Compare(env, obj)) {
540 DelDeletingSubscriber((*it));
541 subscriberInstances_.erase(it);
542 return true;
543 }
544 }
545 return false;
546 }
GetNotificationSubscriber(ani_env * env,ani_object value,std::shared_ptr<StsSubscriberInstance> & subscriberInfo)547 bool SubscriberInstanceManager::GetNotificationSubscriber(
548 ani_env *env, ani_object value, std::shared_ptr<StsSubscriberInstance> &subscriberInfo)
549 {
550 ANS_LOGD("enter");
551 subscriberInfo = std::make_shared<StsSubscriberInstance>();
552 if (!subscriberInfo->SetObject(env, value)) {
553 ANS_LOGD("SetObject faild");
554 return false;
555 }
556 return true;
557 }
AddDeletingSubscriber(std::shared_ptr<StsSubscriberInstance> subscriber)558 bool SubscriberInstanceManager::AddDeletingSubscriber(std::shared_ptr<StsSubscriberInstance> subscriber)
559 {
560 ANS_LOGD("enter");
561 std::lock_guard<std::mutex> lock(delMutex_);
562 if (subscriber == nullptr) return false;
563 auto iter = std::find(DeletingSubscriber.begin(), DeletingSubscriber.end(), subscriber);
564 if (iter != DeletingSubscriber.end()) {
565 return false;
566 }
567 DeletingSubscriber.push_back(subscriber);
568 return true;
569 }
DelDeletingSubscriber(std::shared_ptr<StsSubscriberInstance> subscriber)570 void SubscriberInstanceManager::DelDeletingSubscriber(std::shared_ptr<StsSubscriberInstance> subscriber)
571 {
572 ANS_LOGD("enter");
573 std::lock_guard<std::mutex> lock(delMutex_);
574 auto iter = std::find(DeletingSubscriber.begin(), DeletingSubscriber.end(), subscriber);
575 if (iter != DeletingSubscriber.end()) {
576 DeletingSubscriber.erase(iter);
577 }
578 }
579
Subscribe(ani_env * env,ani_object subscriber,ani_object info)580 bool SubscriberInstanceManager::Subscribe(ani_env *env, ani_object subscriber, ani_object info)
581 {
582 bool isSubscribeUndefine = IsUndefine(env, subscriber);
583 bool isInfoUndefine = IsUndefine(env, info);
584 if (isSubscribeUndefine) {
585 ANS_LOGD("subscriber is undefine");
586 OHOS::NotificationSts::ThrowError(env, ERROR_PARAM_INVALID, "subscriber is undefine");
587 return false;
588 }
589 sptr<OHOS::Notification::NotificationSubscribeInfo> SubscribeInfo =
590 new (std::nothrow) OHOS::Notification::NotificationSubscribeInfo();
591 if (SubscribeInfo == nullptr) {
592 return false;
593 }
594 if (!isInfoUndefine) {
595 if (!UnwarpNotificationSubscribeInfo(env, info, *SubscribeInfo)) {
596 ANS_LOGD("UnwarpNotificationSubscribeInfo faild");
597 OHOS::NotificationSts::ThrowError(env, ERROR_PARAM_INVALID, "UnwarpNotificationSubscribeInfo faild");
598 return false;
599 }
600 }
601 std::shared_ptr<StsSubscriberInstance> stsSubscriber = nullptr;
602 if (!HasNotificationSubscriber(env, subscriber, stsSubscriber)) {
603 if (!GetNotificationSubscriber(env, subscriber, stsSubscriber)) {
604 ANS_LOGD("GetNotificationSubscriber faild");
605 OHOS::NotificationSts::ThrowError(env, ERROR_INTERNAL_ERROR, "GetNotificationSubscriber faild");
606 return false;
607 }
608 if (!AddSubscriberInstancesInfo(env, stsSubscriber)) {
609 ANS_LOGD("AddSubscriberInstancesInfo faild");
610 OHOS::NotificationSts::ThrowError(env, ERROR_INTERNAL_ERROR, "GetNotificationSubscriber faild");
611 return false;
612 }
613 }
614 ErrCode status = ERR_OK;
615 if (!isInfoUndefine) {
616 status = NotificationHelper::SubscribeNotification(stsSubscriber, SubscribeInfo);
617 } else {
618 status = NotificationHelper::SubscribeNotification(stsSubscriber);
619 }
620 if (status != ERR_OK) {
621 int32_t externalErrorCode = GetExternalCode(status);
622 externalErrorCode = (externalErrorCode == ERR_OK) ? status : externalErrorCode;
623 ANS_LOGD("SubscribeNotification faild. status %{public}d ErrorToExternal %{public}d",
624 status, externalErrorCode);
625 std::string msg = OHOS::NotificationSts::FindAnsErrMsg(externalErrorCode);
626 OHOS::NotificationSts::ThrowError(env, externalErrorCode, msg);
627 return false;
628 }
629 return true;
630 }
631
UnSubscribe(ani_env * env,ani_object subscriber)632 bool SubscriberInstanceManager::UnSubscribe(ani_env *env, ani_object subscriber)
633 {
634 ANS_LOGD("enter");
635 if (IsUndefine(env, subscriber)) {
636 ANS_LOGD("Subscriber is undefine");
637 std::string msg = OHOS::NotificationSts::FindAnsErrMsg(ERROR_PARAM_INVALID);
638 OHOS::NotificationSts::ThrowError(env, ERROR_PARAM_INVALID, msg);
639 return false;
640 }
641 std::shared_ptr<StsSubscriberInstance> stsSubscriber = nullptr;
642 if (!HasNotificationSubscriber(env, subscriber, stsSubscriber)) {
643 ANS_LOGD("Subscriber not found");
644 std::string msg = OHOS::NotificationSts::FindAnsErrMsg(ERROR_PARAM_INVALID);
645 OHOS::NotificationSts::ThrowError(env, ERROR_PARAM_INVALID, msg);
646 return false;
647 }
648 bool ret = AddDeletingSubscriber(stsSubscriber);
649 if (ret) {
650 int32_t status = NotificationHelper::UnSubscribeNotification(stsSubscriber);
651 if (status != ERR_OK) {
652 int32_t externalErrorCode = GetExternalCode(status);
653 externalErrorCode = (externalErrorCode == ERR_OK) ? status : externalErrorCode;
654 ANS_LOGD("UnSubscribe faild. status %{public}d ErrorToExternal %{public}d",
655 status, externalErrorCode);
656 std::string msg = OHOS::NotificationSts::FindAnsErrMsg(externalErrorCode);
657 OHOS::NotificationSts::ThrowError(env, externalErrorCode, msg);
658 DelDeletingSubscriber(stsSubscriber);
659 }
660 } else {
661 std::string msg = OHOS::NotificationSts::FindAnsErrMsg(ERROR_INTERNAL_ERROR);
662 OHOS::NotificationSts::ThrowError(env, ERROR_INTERNAL_ERROR, "Subscriber is deleting");
663 return false;
664 }
665 return true;
666 }
667
SubscribeSelf(ani_env * env,ani_object subscriber)668 bool SubscriberInstanceManager::SubscribeSelf(ani_env *env, ani_object subscriber)
669 {
670 ANS_LOGD("enter");
671 bool isSubscribeUndefine = IsUndefine(env, subscriber);
672 if (isSubscribeUndefine) {
673 ANS_LOGD("subscriber is undefine");
674 OHOS::NotificationSts::ThrowError(env, ERROR_PARAM_INVALID, "subscriber is undefine");
675 return false;
676 }
677 std::shared_ptr<StsSubscriberInstance> stsSubscriber = nullptr;
678 if (!HasNotificationSubscriber(env, subscriber, stsSubscriber)) {
679 if (!GetNotificationSubscriber(env, subscriber, stsSubscriber)) {
680 ANS_LOGD("GetNotificationSubscriber faild");
681 OHOS::NotificationSts::ThrowError(env, ERROR_INTERNAL_ERROR, "GetNotificationSubscriber faild");
682 return false;
683 }
684 if (!AddSubscriberInstancesInfo(env, stsSubscriber)) {
685 ANS_LOGD("AddSubscriberInstancesInfo faild");
686 OHOS::NotificationSts::ThrowError(env, ERROR_INTERNAL_ERROR, "GetNotificationSubscriber faild");
687 return false;
688 }
689 }
690 ErrCode status = ERR_OK;
691 status = NotificationHelper::SubscribeNotificationSelf(stsSubscriber);
692 if (status != ERR_OK) {
693 int32_t externalErrorCode = GetExternalCode(status);
694 externalErrorCode = (externalErrorCode == ERR_OK) ? status : externalErrorCode;
695 ANS_LOGD("SubscribeNotificationSelf faild. status %{public}d ErrorToExternal %{public}d",
696 status, externalErrorCode);
697 std::string msg = OHOS::NotificationSts::FindAnsErrMsg(externalErrorCode);
698 OHOS::NotificationSts::ThrowError(env, externalErrorCode, msg);
699 return false;
700 }
701 return true;
702 }
703
GetDoubleValueByClassName(ani_env * env,ani_object param,const char * className,const char * name,ani_double & value)704 bool GetDoubleValueByClassName(
705 ani_env *env, ani_object param, const char *className, const char *name, ani_double &value)
706 {
707 ani_class cls;
708 if (ANI_OK != env->FindClass(className, &cls)) {
709 ANS_LOGD("FindClass faild. %{public}s", className);
710 return false;
711 }
712 ani_method idGetter;
713 if (ANI_OK != env->Class_FindMethod(cls, name, nullptr, &idGetter)) {
714 ANS_LOGD("Class_FindMethod faild. %{public}s", className);
715 return false;
716 }
717 if (ANI_OK != env->Object_CallMethod_Double(param, idGetter, &value)) {
718 ANS_LOGD("Object_CallMethod_Double faild. %{public}s", className);
719 return false;
720 }
721 return true;
722 }
723
UnWarpReasonEnum(ani_env * env,const ani_object enumItem,int32_t & outEnum)724 bool UnWarpReasonEnum(ani_env *env, const ani_object enumItem, int32_t &outEnum)
725 {
726 ani_status status = ANI_ERROR;
727 ani_int intValue{};
728 status = env->EnumItem_GetValue_Int(static_cast<ani_enum_item>(enumItem), &intValue);
729 if (ANI_OK != status) {
730 ANS_LOGD("EnumItem_GetValue_Int failed, status : %{public}d", status);
731 return false;
732 }
733 outEnum = static_cast<int32_t>(intValue);
734 return true;
735 }
736
IsValidRemoveReason(int32_t reasonType)737 bool IsValidRemoveReason(int32_t reasonType)
738 {
739 if (reasonType == OHOS::Notification::NotificationConstant::CLICK_REASON_DELETE ||
740 reasonType == OHOS::Notification::NotificationConstant::CANCEL_REASON_DELETE) {
741 return true;
742 }
743 ANS_LOGD("Reason %{public}d is an invalid value", reasonType);
744 return false;
745 }
746
UnWarpNotificationKey(ani_env * env,const ani_object obj,NotificationKey & OutObj)747 bool UnWarpNotificationKey(ani_env *env, const ani_object obj, NotificationKey &OutObj)
748 {
749 ani_boolean isUndefined = ANI_TRUE;
750 ani_double idDouble = 0.0;
751 if (!GetDoubleValueByClassName(env, obj,
752 "L@ohos/notificationSubscribe/notificationSubscribe/NotificationKeyInner;", "<get>id", idDouble)) {
753 ANS_LOGD("GetDoubleValueByClassName id fail");
754 return false;
755 }
756 OutObj.id = static_cast<int32_t>(idDouble);
757 std::string label;
758 if (GetPropertyString(env, obj, "label", isUndefined, label) != ANI_OK || isUndefined == ANI_TRUE) {
759 ANS_LOGD("UnWarpNotificationKey GetPropertyString label fail");
760 return false;
761 }
762 OutObj.label = GetResizeStr(label, STR_MAX_SIZE);
763 ANS_LOGD("UnWarpNotificationKey id: %{public}d, label: %{public}s", OutObj.id, OutObj.label.c_str());
764 return true;
765 }
766
UnwarpOperationInfo(ani_env * env,const ani_object obj,StsNotificationOperationInfo & outObj)767 bool UnwarpOperationInfo(ani_env *env, const ani_object obj, StsNotificationOperationInfo &outObj)
768 {
769 ani_boolean isUndefined = ANI_TRUE;
770 std::string actionName;
771 std::string userInput;
772 if (GetPropertyString(env, obj, "actionName", isUndefined, actionName) != ANI_OK || isUndefined == ANI_TRUE) {
773 ANS_LOGD("ConvertOperationInfoToNative GetStringOrUndefined actionName fail");
774 return false;
775 }
776 outObj.SetActionName(GetResizeStr(actionName, STR_MAX_SIZE));
777 if (GetPropertyString(env, obj, "userInput", isUndefined, userInput) != ANI_OK || isUndefined == ANI_TRUE) {
778 ANS_LOGD("ConvertOperationInfoToNative GetStringOrUndefined userInput fail");
779 return false;
780 }
781 outObj.SetUserInput(GetResizeStr(userInput, LONG_STR_MAX_SIZE));
782 return true;
783 }
784
GetOperationInfoForDistributeOperation(ani_env * env,ani_string hashcode,ani_object operationInfo,bool & noWithOperationInfo)785 sptr<StsNotificationOperationInfo> GetOperationInfoForDistributeOperation(
786 ani_env *env, ani_string hashcode, ani_object operationInfo, bool &noWithOperationInfo)
787 {
788 std::string hashCodeStd;
789 sptr<StsNotificationOperationInfo> info = new (std::nothrow) StsNotificationOperationInfo();
790 if (ANI_OK != GetStringByAniString(env, hashcode, hashCodeStd)) {
791 ANS_LOGD("hashCode is valid");
792 return nullptr;
793 }
794 info->SetHashCode(hashCodeStd);
795 noWithOperationInfo = IsUndefine(env, operationInfo);
796 if (!noWithOperationInfo) {
797 if (!UnwarpOperationInfo(env, operationInfo, *info)) {
798 ANS_LOGD("operationInfo is valid");
799 return nullptr;
800 }
801 ANS_LOGD("OperationInfo %{public}s %{public}s",
802 info->GetActionName().c_str(), info->GetUserInput().c_str());
803 info->SetOperationType(OperationType::DISTRIBUTE_OPERATION_REPLY);
804 } else {
805 info->SetOperationType(OperationType::DISTRIBUTE_OPERATION_JUMP);
806 }
807 return info;
808 }
809 } // namespace NotificationSts
810 } // OHOS
811