• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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