* Copyright (c) 2021-2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "subscribe.h"
#include "pixelmap_cache_manager.h"
#include "subscriber_image_util.h"
#include "ans_inner_errors.h"
#include "ans_service_errors.h"
#include <mutex>
#include <uv.h>
#include "hitrace_util.h"
#include "notification_classification.h"
namespace OHOS {
namespace NotificationNapi {
const int32_t SUBSCRIBE_NOTIFICATION_MAX_PARA = 2;
const int32_t SUBSCRIBE_MAX_PARA = 3;
const int32_t NO_DELETE_REASON = -1;
const int32_t DISTRIBUTE_JUMP_PARA = 1;
const int32_t DISTRIBUTE_REPLY_PARA = 2;
const std::string CONSUME = "onConsume";
const std::string CANCEL = "onCancel";
const std::string UPDATE = "onUpdate";
const std::string CONNECTED = "onConnect";
const std::string DIS_CONNECTED = "onDisconnect";
const std::string DIE = "onDestroy";
const std::string DISTURB_MODE_CHANGE = "onDisturbModeChange";
const std::string DISTURB_DATE_CHANGE = "onDoNotDisturbDateChange";
const std::string DISTURB_CHANGED = "onDoNotDisturbChanged";
const std::string ENABLE_NOTIFICATION_CHANGED = "OnEnabledNotificationChanged";
const std::string ENABLE_SILENT_REMINDER_CHANGED = "OnEnabledSilentReminderChanged";
const std::string ENABLE_PRIORITY_CHANGED = "OnEnabledPriorityChanged";
const std::string ENABLE_PRIORITY_BY_BUNDLE_CHANGED = "OnEnabledPriorityByBundleChanged";
const std::string SYSTEM_UPDATE = "OnSystemUpdate";
const std::string BADGE_CHANGED = "OnBadgeChanged";
const std::string BADGE_ENABLED_CHANGED = "OnBadgeEnabledChanged";
const std::string BATCH_CANCEL = "onBatchCancel";
const std::string NOTIFICATION_SWITCH_CHANGED = "OnNotificationSwitchChanged";
enum class Type {
UNKNOWN,
CANCEL,
BATCH_CANCEL,
CONSUME,
UPDATE,
CONNECTED,
DIS_CONNECTED,
DIE,
DISTURB_DATE_CHANGE,
DISTURB_CHANGED,
ENABLE_NOTIFICATION_CHANGED,
BADGE_CHANGED,
BADGE_ENABLED_CHANGED,
ENABLE_PRIORITY_CHANGED,
ENABLE_PRIORITY_BY_BUNDLE_CHANGED,
SYSTEM_UPDATE,
ENABLE_SILENT_REMINDER_CHANGED,
NOTIFICATION_SWITCH_CHANGED
};
struct NotificationReceiveDataWorker {
std::shared_ptr<OHOS::Notification::Notification> request;
std::vector<std::shared_ptr<OHOS::Notification::Notification>> requestList;
std::shared_ptr<NotificationSortingMap> sortingMap;
NotificationDoNotDisturbDate date;
EnabledNotificationCallbackData callbackData;
EnabledSilentReminderCallbackData silentReminderCallbackData;
EnabledPriorityNotificationByBundleCallbackData priorityCallbackData;
NotificationSwitchChangedCallbackData notificationSwitchChangedCallbackData;
BadgeNumberCallbackData badge;
int32_t deleteReason = 0;
bool priorityEnable = false;
int32_t result = 0;
int32_t disturbMode = 0;
std::weak_ptr<SubscriberInstance> subscriber;
Type type;
};
napi_value SetSubscribeCallbackData(const napi_env &env,
const std::shared_ptr<OHOS::Notification::Notification> &request,
const std::shared_ptr<NotificationSortingMap> &sortingMap, int32_t deleteReason, napi_value &result)
{
ANS_LOGD("called");
if (request == nullptr) {
ANS_LOGE("null request");
return Common::NapiGetBoolean(env, false);
}
napi_value requestResult = nullptr;
napi_create_object(env, &requestResult);
if (!Common::SetNotification(env, request.get(), requestResult)) {
ANS_LOGE("SetNotification call failed");
return Common::NapiGetBoolean(env, false);
}
napi_set_named_property(env, result, "request", requestResult);
if (sortingMap != nullptr) {
napi_value sortingMapResult = nullptr;
napi_create_object(env, &sortingMapResult);
if (!Common::SetNotificationSortingMap(env, sortingMap, sortingMapResult)) {
ANS_LOGE("SetNotificationSortingMap call failed");
return Common::NapiGetBoolean(env, false);
}
napi_set_named_property(env, result, "sortingMap", sortingMapResult);
}
if (deleteReason != NO_DELETE_REASON) {
napi_value value = nullptr;
int32_t outReason = 0;
if (!AnsEnumUtil::ReasonCToJS(deleteReason, outReason)) {
return Common::NapiGetBoolean(env, false);
}
napi_create_int32(env, outReason, &value);
napi_set_named_property(env, result, "reason", value);
}
napi_value soundResult = nullptr;
std::string sound;
if (request->EnableSound()) {
sound = request->GetSound().ToString();
}
napi_create_string_utf8(env, sound.c_str(), NAPI_AUTO_LENGTH, &soundResult);
napi_set_named_property(env, result, "sound", soundResult);
napi_value arr = nullptr;
napi_create_array(env, &arr);
if (request->EnableVibrate()) {
uint32_t count = 0;
for (auto vec : request->GetVibrationStyle()) {
napi_value nVibrationValue = nullptr;
napi_create_int64(env, vec, &nVibrationValue);
napi_set_element(env, arr, count, nVibrationValue);
count++;
}
}
napi_set_named_property(env, result, "vibrationValues", arr);
auto voiceContent = request->GetVoiceContent();
if (voiceContent != nullptr) {
napi_value voiceContentResult = nullptr;
napi_create_object(env, &voiceContentResult);
if (!Common::SetNotificationVoiceContent(env, *voiceContent, voiceContentResult)) {
ANS_LOGE("SetNotificationVoiceContent call failed");
return Common::NapiGetBoolean(env, false);
}
napi_set_named_property(env, result, "voiceContent", voiceContentResult);
}
auto notificationClassification = request->GetNotificationClassification();
if (notificationClassification != nullptr) {
napi_value notificationClassificationNapi = nullptr;
napi_create_object(env, ¬ificationClassificationNapi);
if (!Common::SetNotificationClassification(env, *notificationClassification, notificationClassificationNapi)) {
ANS_LOGE("SetNotificationClassification call failed");
return Common::NapiGetBoolean(env, false);
}
napi_set_named_property(env, result, "notificationClassification", notificationClassificationNapi);
}
return Common::NapiGetBoolean(env, true);
}
napi_value SetPriorityCallbackData(const napi_env &env, const bool enable, napi_value &result)
{
ANS_LOGD("called");
napi_value value = nullptr;
napi_get_boolean(env, enable, &value);
napi_set_named_property(env, result, "enable", value);
return Common::NapiGetBoolean(env, true);
}
static void ClearEnvCallback(void *data)
{
ANS_LOGD("Env expired, need to clear env");
SubscriberInstance *subscriber = reinterpret_cast<SubscriberInstance *>(data);
subscriber->ClearEnv();
}
SubscriberInstance::SubscriberInstance()
{}
SubscriberInstance::~SubscriberInstance()
{}
void SubscriberInstance::SubDeleteRef()
{
if (enabledPriorityCallbackInfo_.ref != nullptr) {
napi_delete_reference(enabledPriorityCallbackInfo_.env, enabledPriorityCallbackInfo_.ref);
enabledPriorityCallbackInfo_.ref = nullptr;
}
if (enabledPriorityByBundleCallbackInfo_.ref != nullptr) {
napi_delete_reference(enabledPriorityByBundleCallbackInfo_.env, enabledPriorityByBundleCallbackInfo_.ref);
enabledPriorityByBundleCallbackInfo_.ref = nullptr;
}
if (systemUpdateCallbackInfo_.ref != nullptr) {
napi_delete_reference(systemUpdateCallbackInfo_.env, systemUpdateCallbackInfo_.ref);
systemUpdateCallbackInfo_.ref = nullptr;
}
if (notificationSwitchChangedCallbackInfo_.ref != nullptr) {
napi_delete_reference(notificationSwitchChangedCallbackInfo_.env, notificationSwitchChangedCallbackInfo_.ref);
notificationSwitchChangedCallbackInfo_.ref = nullptr;
}
if (disturbDateCallbackInfo_.ref != nullptr) {
napi_delete_reference(disturbDateCallbackInfo_.env, disturbDateCallbackInfo_.ref);
disturbDateCallbackInfo_.ref = nullptr;
}
if (disturbChangedCallbackInfo_.ref != nullptr) {
napi_delete_reference(disturbChangedCallbackInfo_.env, disturbChangedCallbackInfo_.ref);
disturbChangedCallbackInfo_.ref = nullptr;
}
if (enabledSilentReminderCallbackInfo_.ref != nullptr) {
napi_delete_reference(enabledSilentReminderCallbackInfo_.env, enabledSilentReminderCallbackInfo_.ref);
enabledSilentReminderCallbackInfo_.ref = nullptr;
}
if (setBadgeCallbackInfo_.ref != nullptr) {
napi_delete_reference(setBadgeCallbackInfo_.env, setBadgeCallbackInfo_.ref);
setBadgeCallbackInfo_.ref = nullptr;
}
if (setBadgeEnabledCallbackInfo_.ref != nullptr) {
napi_delete_reference(setBadgeEnabledCallbackInfo_.env, setBadgeEnabledCallbackInfo_.ref);
setBadgeEnabledCallbackInfo_.ref = nullptr;
}
}
void SubscriberInstance::DeleteRef()
{
{
std::lock_guard<ffrt::mutex> lock(tsfnMutex_);
if (tsfn_ != nullptr) {
napi_release_threadsafe_function(tsfn_, napi_tsfn_release);
tsfn_ = nullptr;
}
}
if (canceCallbackInfo_.ref != nullptr) {
napi_delete_reference(canceCallbackInfo_.env, canceCallbackInfo_.ref);
canceCallbackInfo_.ref = nullptr;
}
if (consumeCallbackInfo_.ref != nullptr) {
napi_delete_reference(consumeCallbackInfo_.env, consumeCallbackInfo_.ref);
consumeCallbackInfo_.ref = nullptr;
}
if (updateCallbackInfo_.ref != nullptr) {
napi_delete_reference(updateCallbackInfo_.env, updateCallbackInfo_.ref);
updateCallbackInfo_.ref = nullptr;
}
if (subscribeCallbackInfo_.ref != nullptr) {
napi_delete_reference(subscribeCallbackInfo_.env, subscribeCallbackInfo_.ref);
subscribeCallbackInfo_.ref = nullptr;
}
if (unsubscribeCallbackInfo_.ref != nullptr) {
napi_delete_reference(unsubscribeCallbackInfo_.env, unsubscribeCallbackInfo_.ref);
unsubscribeCallbackInfo_.ref = nullptr;
}
if (dieCallbackInfo_.ref != nullptr) {
napi_delete_reference(dieCallbackInfo_.env, dieCallbackInfo_.ref);
dieCallbackInfo_.ref = nullptr;
}
if (disturbModeCallbackInfo_.ref != nullptr) {
napi_delete_reference(disturbModeCallbackInfo_.env, disturbModeCallbackInfo_.ref);
disturbModeCallbackInfo_.ref = nullptr;
}
if (enabledNotificationCallbackInfo_.ref != nullptr) {
napi_delete_reference(enabledNotificationCallbackInfo_.env, enabledNotificationCallbackInfo_.ref);
enabledNotificationCallbackInfo_.ref = nullptr;
}
if (batchCancelCallbackInfo_.ref != nullptr) {
napi_delete_reference(batchCancelCallbackInfo_.env, batchCancelCallbackInfo_.ref);
batchCancelCallbackInfo_.ref = nullptr;
}
SubDeleteRef();
if (env_ != nullptr) {
napi_remove_env_cleanup_hook(env_, ClearEnvCallback, this);
}
}
void SubscriberInstance::ClearEnv()
{
DeleteRef();
env_ = nullptr;
}
void SubscriberInstance::CallThreadSafeFunc(void* data)
{
std::lock_guard<ffrt::mutex> lock(tsfnMutex_);
if (tsfn_ == nullptr) {
auto dataWorker = reinterpret_cast<NotificationReceiveDataWorker *>(data);
delete dataWorker;
dataWorker = nullptr;
ANS_LOGD("null tsfn_");
return;
}
napi_acquire_threadsafe_function(tsfn_);
napi_call_threadsafe_function(tsfn_, data, napi_tsfn_nonblocking);
napi_release_threadsafe_function(tsfn_, napi_tsfn_release);
return;
}
void ThreadSafeOnCancel(napi_env env, napi_value jsCallback, void* context, void* data)
{
ANS_LOGD("called");
auto dataWorkerData = reinterpret_cast<NotificationReceiveDataWorker *>(data);
if (dataWorkerData == nullptr) {
ANS_LOGE("null dataWorkerData");
return;
}
auto subscriber = dataWorkerData->subscriber.lock();
if (subscriber == nullptr) {
ANS_LOGE("null subscriber");
return;
}
napi_value result = nullptr;
napi_handle_scope scope;
auto status = napi_open_handle_scope(env, &scope);
if (status != napi_ok || scope == nullptr) {
ANS_LOGE("status: %{public}d", status);
return;
}
napi_create_object(env, &result);
if (!SetSubscribeCallbackData(env,
dataWorkerData->request,
dataWorkerData->sortingMap,
dataWorkerData->deleteReason,
result)) {
ANS_LOGE("Failed to convert data to JS");
} else {
Common::SetCallback(env, subscriber->GetCallbackInfo(CANCEL).ref, result);
}
napi_close_handle_scope(env, scope);
}
void SubscriberInstance::OnCanceled(const std::shared_ptr<OHOS::Notification::Notification> &request,
const std::shared_ptr<NotificationSortingMap> &sortingMap, int32_t deleteReason)
{
ANS_LOGD("called");
if (canceCallbackInfo_.ref == nullptr || canceCallbackInfo_.env == nullptr) {
return;
}
if (request == nullptr) {
ANS_LOGE("null request");
return;
}
if (sortingMap == nullptr) {
ANS_LOGE("null sortingMap");
return;
}
auto cacheManager = PixelMapCacheManager::GetInstance();
cacheManager->RemoveCache(request->GetNotificationRequest().GetKey());
ANS_LOGI("Cancel Key=%{public}s,sortingMap size=%{public}zu,reason=%{public}d",
request->GetKey().c_str(), sortingMap->GetKey().size(), deleteReason);
ANS_LOGD("SubscriberInstance::OnCanceled instanceKey: %{public}s", request->GetInstanceKey().c_str());
NotificationReceiveDataWorker *dataWorker = new (std::nothrow) NotificationReceiveDataWorker();
if (dataWorker == nullptr) {
ANS_LOGE("null dataWorker");
return;
}
dataWorker->request = request;
dataWorker->sortingMap = sortingMap;
dataWorker->deleteReason = deleteReason;
dataWorker->type = Type::CANCEL;
dataWorker->subscriber = std::static_pointer_cast<SubscriberInstance>(shared_from_this());
CallThreadSafeFunc(dataWorker);
}
void ThreadSafeOnBatchCancel(napi_env env, napi_value jsCallback, void* context, void* data)
{
ANS_LOGD("called");
auto dataWorkerData = reinterpret_cast<NotificationReceiveDataWorker *>(data);
if (dataWorkerData == nullptr) {
ANS_LOGE("null dataWorkerData");
return;
}
auto subscriber = dataWorkerData->subscriber.lock();
if (subscriber == nullptr) {
ANS_LOGE("null subscriber");
return;
}
napi_value resultArray = nullptr;
napi_handle_scope scope;
auto status = napi_open_handle_scope(env, &scope);
if (status != napi_ok || scope == nullptr) {
ANS_LOGE("status: %{public}d", status);
return;
}
napi_create_array(env, &resultArray);
int index = 0;
for (auto request : dataWorkerData->requestList) {
napi_value result = nullptr;
napi_create_object(env, &result);
if (SetSubscribeCallbackData(env, request,
dataWorkerData->sortingMap, dataWorkerData->deleteReason, result)) {
napi_set_element(env, resultArray, index, result);
index++;
}
}
uint32_t elementCount = 0;
napi_get_array_length(env, resultArray, &elementCount);
ANS_LOGD("BatchCancel size:%{public}d", elementCount);
if (elementCount > 0) {
Common::SetCallback(env, subscriber->GetCallbackInfo(BATCH_CANCEL).ref, resultArray);
}
napi_close_handle_scope(env, scope);
}
void SubscriberInstance::OnBatchCanceled(const std::vector<std::shared_ptr<OHOS::Notification::Notification>>
&requestList, const std::shared_ptr<NotificationSortingMap> &sortingMap, int32_t deleteReason)
{
if (batchCancelCallbackInfo_.ref == nullptr || batchCancelCallbackInfo_.env == nullptr) {
return;
}
if (requestList.empty()) {
ANS_LOGE("empty requestList");
return;
}
if (sortingMap == nullptr) {
ANS_LOGE("null sortingMap");
return;
}
auto cacheManager = PixelMapCacheManager::GetInstance();
std::string notificationKeys = "";
for (auto notification : requestList) {
notificationKeys.append(notification->GetNotificationRequest().GetKey()).append("-");
if (notification != nullptr) {
cacheManager->RemoveCache(notification->GetNotificationRequest().GetKey());
}
}
ANS_LOGI("BatchCancel reason=%{public}d,sortingMap size=%{public}zu,keys=%{public}s",
deleteReason, sortingMap->GetKey().size(), notificationKeys.c_str());
NotificationReceiveDataWorker *dataWorker = new (std::nothrow) NotificationReceiveDataWorker();
if (dataWorker == nullptr) {
ANS_LOGE("null dataWorker");
return;
}
dataWorker->requestList = requestList;
dataWorker->sortingMap = sortingMap;
dataWorker->deleteReason = deleteReason;
dataWorker->type = Type::BATCH_CANCEL;
dataWorker->subscriber = std::static_pointer_cast<SubscriberInstance>(shared_from_this());
CallThreadSafeFunc(dataWorker);
return;
}
bool SubscriberInstance::HasOnBatchCancelCallback()
{
if (batchCancelCallbackInfo_.ref == nullptr) {
ANS_LOGE("null ref");
return false;
}
return true;
}
void ThreadSafeOnConsumed(napi_env env, napi_value jsCallback, void* context, void* data)
{
ANS_LOGD("called");
auto dataWorkerData = reinterpret_cast<NotificationReceiveDataWorker *>(data);
auto additionalData = dataWorkerData->request->GetNotificationRequest().GetAdditionalData();
if (additionalData && additionalData->HasParam("_oh_ans_sys_traceid")) {
std::stringstream sin(additionalData->GetStringParam("_oh_ans_sys_traceid"));
uint64_t chainId;
if (sin >> std::hex >> chainId) {
TraceChainUtil traceChainUtil = TraceChainUtil();
OHOS::HiviewDFX::HiTraceId traceId = OHOS::HiviewDFX::HiTraceChain::GetId();
traceId.SetChainId(chainId);
OHOS::HiviewDFX::HiTraceChain::SetId(traceId);
}
}
ANS_LOGD("called");
if (dataWorkerData == nullptr) {
ANS_LOGE("null dataWorkerData");
return;
}
auto subscriber = dataWorkerData->subscriber.lock();
if (subscriber == nullptr) {
ANS_LOGE("null subscriber");
return;
}
napi_value result = nullptr;
napi_handle_scope scope;
auto status = napi_open_handle_scope(env, &scope);
if (status != napi_ok || scope == nullptr) {
ANS_LOGE("status: %{public}d", status);
return;
}
napi_create_object(env, &result);
if (!SetSubscribeCallbackData(env,
dataWorkerData->request,
dataWorkerData->sortingMap,
NO_DELETE_REASON,
result)) {
ANS_LOGE("Convert data to JS fail.");
} else {
Common::SetCallback(env, subscriber->GetCallbackInfo(CONSUME).ref, result);
}
napi_close_handle_scope(env, scope);
}
void SubscriberInstance::OnConsumed(const std::shared_ptr<OHOS::Notification::Notification> &request,
const std::shared_ptr<NotificationSortingMap> &sortingMap)
{
ANS_LOGD("called");
if (consumeCallbackInfo_.ref == nullptr || consumeCallbackInfo_.env == nullptr) {
return;
}
if (request == nullptr) {
ANS_LOGE("null request");
return;
}
if (sortingMap == nullptr) {
ANS_LOGE("null sortingMap");
return;
}
SubscriberImageUtil::ProcessPictureOption(request, GetPictureOption());
auto notificationFlags = request->GetNotificationRequest().GetFlags();
ANS_LOGI("onConsume key=%{public}s n=%{public}zu flags=%{public}d",
request->GetKey().c_str(), sortingMap->GetKey().size(),
notificationFlags == nullptr ? -1 : static_cast<int>(notificationFlags->GetReminderFlags()));
ANS_LOGD("OnConsumed instanceKey: %{public}s", request->GetInstanceKey().c_str());
NotificationReceiveDataWorker *dataWorker = new (std::nothrow) NotificationReceiveDataWorker();
if (dataWorker == nullptr) {
ANS_LOGE("null dataWorker");
return;
}
dataWorker->request = request;
dataWorker->sortingMap = sortingMap;
dataWorker->type = Type::CONSUME;
dataWorker->subscriber = std::static_pointer_cast<SubscriberInstance>(shared_from_this());
CallThreadSafeFunc(dataWorker);
}
void ThreadSafeOnUpdate(napi_env env, napi_value jsCallback, void* context, void* data)
{
ANS_LOGD("called");
auto dataWorkerData = reinterpret_cast<NotificationReceiveDataWorker *>(data);
if (dataWorkerData == nullptr) {
ANS_LOGE("null dataWorkerData");
return;
}
auto subscriber = dataWorkerData->subscriber.lock();
if (subscriber == nullptr) {
ANS_LOGE("null subscriber");
return;
}
napi_value result = nullptr;
napi_handle_scope scope;
auto status = napi_open_handle_scope(env, &scope);
if (status != napi_ok || scope == nullptr) {
ANS_LOGE("status: %{public}d", status);
return;
}
napi_create_object(env, &result);
if (!Common::SetNotificationSortingMap(env, dataWorkerData->sortingMap, result)) {
ANS_LOGE("Failed to convert data to JS");
} else {
Common::SetCallback(env, subscriber->GetCallbackInfo(UPDATE).ref, result);
}
napi_close_handle_scope(env, scope);
}
void SubscriberInstance::OnUpdate(const std::shared_ptr<NotificationSortingMap> &sortingMap)
{
ANS_LOGD("called");
if (updateCallbackInfo_.ref == nullptr || updateCallbackInfo_.env == nullptr) {
return;
}
if (sortingMap == nullptr) {
ANS_LOGE("null sortingMap");
return;
}
ANS_LOGI("update sortingMap size=%{public}zu", sortingMap->GetKey().size());
NotificationReceiveDataWorker *dataWorker = new (std::nothrow) NotificationReceiveDataWorker();
if (dataWorker == nullptr) {
ANS_LOGE("null dataWorker");
return;
}
dataWorker->sortingMap = sortingMap;
dataWorker->type = Type::UPDATE;
dataWorker->subscriber = std::static_pointer_cast<SubscriberInstance>(shared_from_this());
CallThreadSafeFunc(dataWorker);
}
void ThreadSafeOnConnected(napi_env env, napi_value jsCallback, void* context, void* data)
{
ANS_LOGD("called");
auto dataWorkerData = reinterpret_cast<NotificationReceiveDataWorker *>(data);
if (dataWorkerData == nullptr) {
ANS_LOGE("null dataWorkerData");
return;
}
auto subscriber = dataWorkerData->subscriber.lock();
if (subscriber == nullptr) {
ANS_LOGE("null subscriber");
return;
}
Common::SetCallback(env, subscriber->GetCallbackInfo(CONNECTED).ref, Common::NapiGetNull(env));
}
void SubscriberInstance::OnConnected()
{
ANS_LOGD("called");
if (subscribeCallbackInfo_.ref == nullptr || subscribeCallbackInfo_.env == nullptr) {
return;
}
NotificationReceiveDataWorker *dataWorker = new (std::nothrow) NotificationReceiveDataWorker();
if (dataWorker == nullptr) {
ANS_LOGE("null dataWorker");
return;
}
dataWorker->type = Type::CONNECTED;
dataWorker->subscriber = std::static_pointer_cast<SubscriberInstance>(shared_from_this());
CallThreadSafeFunc(dataWorker);
}
void ThreadSafeOnDisconnected(napi_env env, napi_value jsCallback, void* context, void* data)
{
ANS_LOGD("called");
auto dataWorkerData = reinterpret_cast<NotificationReceiveDataWorker *>(data);
if (dataWorkerData == nullptr) {
ANS_LOGE("null dataWorkerData.");
return;
}
auto subscriber = dataWorkerData->subscriber.lock();
if (subscriber == nullptr) {
ANS_LOGE("null subscriber");
return;
}
if (subscriber->GetCallbackInfo(DIS_CONNECTED).ref == nullptr) {
ANS_LOGD("unsubscribe callback unset");
DelSubscriberInstancesInfo(env, subscriber);
return;
}
Common::SetCallback(env, subscriber->GetCallbackInfo(DIS_CONNECTED).ref, Common::NapiGetNull(env));
DelSubscriberInstancesInfo(env, subscriber);
}
void SubscriberInstance::OnDisconnected()
{
ANS_LOGD("called");
NotificationReceiveDataWorker *dataWorker = new (std::nothrow) NotificationReceiveDataWorker();
if (dataWorker == nullptr) {
ANS_LOGE("null dataWorker");
return;
}
dataWorker->type = Type::DIS_CONNECTED;
dataWorker->subscriber = std::static_pointer_cast<SubscriberInstance>(shared_from_this());
CallThreadSafeFunc(dataWorker);
}
void ThreadSafeOnDestroy(napi_env env, napi_value jsCallback, void* context, void* data)
{
ANS_LOGD("called");
auto dataWorkerData = reinterpret_cast<NotificationReceiveDataWorker *>(data);
if (dataWorkerData == nullptr) {
ANS_LOGE("null dataWorkerData");
return;
}
auto subscriber = dataWorkerData->subscriber.lock();
if (subscriber == nullptr) {
ANS_LOGE("null subscriber");
return;
}
Common::SetCallback(
env, subscriber->GetCallbackInfo(DIE).ref, Common::NapiGetNull(env));
}
void SubscriberInstance::OnDied()
{
ANS_LOGD("called");
if (dieCallbackInfo_.ref == nullptr) {
return;
}
NotificationReceiveDataWorker *dataWorker = new (std::nothrow) NotificationReceiveDataWorker();
if (dataWorker == nullptr) {
ANS_LOGE("null dataWorker");
return;
}
dataWorker->type = Type::DIE;
dataWorker->subscriber = std::static_pointer_cast<SubscriberInstance>(shared_from_this());
CallThreadSafeFunc(dataWorker);
}
void ThreadSafeOnDoNotDisturbDateChange(napi_env env, napi_value jsCallback, void* context, void* data)
{
ANS_LOGD("called");
auto dataWorkerData = reinterpret_cast<NotificationReceiveDataWorker *>(data);
if (dataWorkerData == nullptr) {
ANS_LOGE("null dataWorkerData");
return;
}
auto subscriber = dataWorkerData->subscriber.lock();
if (subscriber == nullptr) {
ANS_LOGE("null subscriber");
return;
}
napi_value result = nullptr;
napi_handle_scope scope;
auto status = napi_open_handle_scope(env, &scope);
if (status != napi_ok || scope == nullptr) {
ANS_LOGE("status: %{public}d", status);
return;
}
napi_create_object(env, &result);
if (!Common::SetDoNotDisturbDate(env, dataWorkerData->date, result)) {
result = Common::NapiGetNull(env);
}
Common::SetCallback(env, subscriber->GetCallbackInfo(DISTURB_DATE_CHANGE).ref, result);
napi_close_handle_scope(env, scope);
}
void SubscriberInstance::OnDoNotDisturbDateChange(const std::shared_ptr<NotificationDoNotDisturbDate> &date)
{
ANS_LOGD("called");
onDoNotDisturbChanged(date);
if (disturbDateCallbackInfo_.ref == nullptr || disturbDateCallbackInfo_.env == nullptr) {
return;
}
if (date == nullptr) {
ANS_LOGE("null date");
return;
}
NotificationReceiveDataWorker *dataWorker = new (std::nothrow) NotificationReceiveDataWorker();
if (dataWorker == nullptr) {
ANS_LOGE("null dataWorker");
return;
}
dataWorker->date = *date;
dataWorker->type = Type::DISTURB_DATE_CHANGE;
dataWorker->subscriber = std::static_pointer_cast<SubscriberInstance>(shared_from_this());
CallThreadSafeFunc(dataWorker);
}
void ThreadSafeOnDoNotDisturbChanged(napi_env env, napi_value jsCallback, void* context, void* data)
{
ANS_LOGD("called");
auto dataWorkerData = reinterpret_cast<NotificationReceiveDataWorker *>(data);
if (dataWorkerData == nullptr) {
ANS_LOGE("null dataWorkerData");
return;
}
auto subscriber = dataWorkerData->subscriber.lock();
if (subscriber == nullptr) {
ANS_LOGE("null subscriber");
return;
}
napi_value result = nullptr;
napi_handle_scope scope;
auto status = napi_open_handle_scope(env, &scope);
if (status != napi_ok || scope == nullptr) {
ANS_LOGE("status: %{public}d", status);
return;
}
napi_create_object(env, &result);
if (!Common::SetDoNotDisturbDate(env, dataWorkerData->date, result)) {
result = Common::NapiGetNull(env);
}
Common::SetCallback(env, subscriber->GetCallbackInfo(DISTURB_CHANGED).ref, result);
napi_close_handle_scope(env, scope);
}
void SubscriberInstance::onDoNotDisturbChanged(const std::shared_ptr<NotificationDoNotDisturbDate>& date)
{
ANS_LOGD("called");
if (disturbChangedCallbackInfo_.ref == nullptr || disturbChangedCallbackInfo_.env == nullptr) {
return;
}
if (date == nullptr) {
ANS_LOGE("null date");
return;
}
NotificationReceiveDataWorker* dataWorker = new (std::nothrow) NotificationReceiveDataWorker();
if (dataWorker == nullptr) {
ANS_LOGE("null dataWorker");
return;
}
dataWorker->date = *date;
dataWorker->type = Type::DISTURB_CHANGED;
dataWorker->subscriber = std::static_pointer_cast<SubscriberInstance>(shared_from_this());
CallThreadSafeFunc(dataWorker);
}
void ThreadSafeOnEnabledNotificationChanged(napi_env env, napi_value jsCallback, void* context, void* data)
{
ANS_LOGD("called");
auto dataWorkerData = reinterpret_cast<NotificationReceiveDataWorker *>(data);
if (dataWorkerData == nullptr) {
ANS_LOGE("null dataWorkerData");
return;
}
auto subscriber = dataWorkerData->subscriber.lock();
if (subscriber == nullptr) {
ANS_LOGE("null subscriber");
return;
}
napi_value result = nullptr;
napi_handle_scope scope;
auto status = napi_open_handle_scope(env, &scope);
if (status != napi_ok || scope == nullptr) {
ANS_LOGE("status: %{public}d", status);
return;
}
napi_create_object(env, &result);
if (!Common::SetEnabledNotificationCallbackData(env, dataWorkerData->callbackData, result)) {
result = Common::NapiGetNull(env);
}
Common::SetCallback(env, subscriber->GetCallbackInfo(ENABLE_NOTIFICATION_CHANGED).ref, result);
napi_close_handle_scope(env, scope);
}
void SubscriberInstance::OnEnabledNotificationChanged(
const std::shared_ptr<EnabledNotificationCallbackData> &callbackData)
{
ANS_LOGD("called");
if (enabledNotificationCallbackInfo_.ref == nullptr || enabledNotificationCallbackInfo_.env == nullptr) {
return;
}
if (callbackData == nullptr) {
ANS_LOGE("null callbackData");
return;
}
NotificationReceiveDataWorker *dataWorker = new (std::nothrow) NotificationReceiveDataWorker();
if (dataWorker == nullptr) {
ANS_LOGE("null dataWorker");
return;
}
dataWorker->callbackData = *callbackData;
dataWorker->type = Type::ENABLE_NOTIFICATION_CHANGED;
dataWorker->subscriber = std::static_pointer_cast<SubscriberInstance>(shared_from_this());
CallThreadSafeFunc(dataWorker);
}
void ThreadSafeOnEnabledSilentReminderChanged(napi_env env, napi_value jsCallback, void* context, void* data)
{
ANS_LOGD("called");
auto dataWorkerData = reinterpret_cast<NotificationReceiveDataWorker *>(data);
if (dataWorkerData == nullptr) {
ANS_LOGE("null dataWorkerData");
return;
}
auto subscriber = dataWorkerData->subscriber.lock();
if (subscriber == nullptr) {
ANS_LOGE("null subscriber");
return;
}
napi_value result = nullptr;
napi_handle_scope scope;
auto status = napi_open_handle_scope(env, &scope);
if (status != napi_ok || scope == nullptr) {
ANS_LOGE("status: %{public}d", status);
return;
}
napi_create_object(env, &result);
if (!Common::SetEnabledSilentReminderCallbackData(env, dataWorkerData->silentReminderCallbackData, result)) {
ANS_LOGE("SetEnabledSilentReminderCallbackData failed");
result = Common::NapiGetNull(env);
}
Common::SetCallback(env, subscriber->GetCallbackInfo(ENABLE_SILENT_REMINDER_CHANGED).ref, result);
napi_close_handle_scope(env, scope);
}
void SubscriberInstance::OnEnabledSilentReminderChanged(
const std::shared_ptr<EnabledSilentReminderCallbackData> &callbackData)
{
ANS_LOGD("called");
if (enabledSilentReminderCallbackInfo_.ref == nullptr || enabledSilentReminderCallbackInfo_.env == nullptr) {
return;
}
if (callbackData == nullptr) {
ANS_LOGE("null callbackData");
return;
}
NotificationReceiveDataWorker *dataWorker = new (std::nothrow) NotificationReceiveDataWorker();
if (dataWorker == nullptr) {
ANS_LOGE("null dataWorker");
return;
}
dataWorker->silentReminderCallbackData = *callbackData;
dataWorker->type = Type::ENABLE_SILENT_REMINDER_CHANGED;
dataWorker->subscriber = std::static_pointer_cast<SubscriberInstance>(shared_from_this());
CallThreadSafeFunc(dataWorker);
};
void ThreadSafeOnNotificationSwitchChanged(napi_env env, napi_value jsCallback, void* context, void* data)
{
ANS_LOGD("called");
auto dataWorkerData = reinterpret_cast<NotificationReceiveDataWorker *>(data);
if (dataWorkerData == nullptr) {
ANS_LOGE("null dataWorkerData");
return;
}
auto subscriber = dataWorkerData->subscriber.lock();
if (subscriber == nullptr) {
ANS_LOGE("null subscriber");
return;
}
napi_value result = nullptr;
napi_handle_scope scope;
auto status = napi_open_handle_scope(env, &scope);
if (status != napi_ok || scope == nullptr) {
ANS_LOGE("status: %{public}d", status);
return;
}
napi_create_object(env, &result);
if (!Common::SetNotificationSwitchChangedCallbackData(
env, dataWorkerData->notificationSwitchChangedCallbackData, result)) {
ANS_LOGE("SetNotificationSwitchChangedCallbackData failed");
result = Common::NapiGetNull(env);
}
Common::SetCallback(env, subscriber->GetCallbackInfo(NOTIFICATION_SWITCH_CHANGED).ref, result);
napi_close_handle_scope(env, scope);
}
void SubscriberInstance::OnNotificationSwitchChanged(
const std::shared_ptr<NotificationSwitchChangedCallbackData> &callbackData)
{
ANS_LOGD("called");
if (notificationSwitchChangedCallbackInfo_.ref == nullptr ||
notificationSwitchChangedCallbackInfo_.env == nullptr) {
return;
}
if (callbackData == nullptr) {
ANS_LOGE("null callbackData");
return;
}
NotificationReceiveDataWorker *dataWorker = new (std::nothrow) NotificationReceiveDataWorker();
if (dataWorker == nullptr) {
ANS_LOGE("null dataWorker");
return;
}
dataWorker->notificationSwitchChangedCallbackData = *callbackData;
dataWorker->type = Type::NOTIFICATION_SWITCH_CHANGED;
dataWorker->subscriber = std::static_pointer_cast<SubscriberInstance>(shared_from_this());
CallThreadSafeFunc(dataWorker);
}
void ThreadSafeOnEnabledPriorityChanged(napi_env env, napi_value jsCallback, void* context, void* data)
{
ANS_LOGD("called");
auto dataWorkerData = reinterpret_cast<NotificationReceiveDataWorker *>(data);
if (dataWorkerData == nullptr) {
ANS_LOGE("null dataWorkerData");
return;
}
auto subscriber = dataWorkerData->subscriber.lock();
if (subscriber == nullptr) {
ANS_LOGE("null subscriber");
return;
}
napi_value result = nullptr;
napi_handle_scope scope;
auto status = napi_open_handle_scope(env, &scope);
if (status != napi_ok || scope == nullptr) {
ANS_LOGE("status: %{public}d", status);
return;
}
napi_create_object(env, &result);
if (!SetPriorityCallbackData(env, dataWorkerData->priorityEnable, result)) {
result = Common::NapiGetNull(env);
} else {
Common::SetCallback(env, subscriber->GetCallbackInfo(ENABLE_PRIORITY_CHANGED).ref, result);
}
napi_close_handle_scope(env, scope);
}
void SubscriberInstance::OnEnabledPriorityChanged(const std::shared_ptr<EnabledNotificationCallbackData> &callbackData)
{
ANS_LOGD("called");
if (enabledPriorityCallbackInfo_.ref == nullptr || enabledPriorityCallbackInfo_.env == nullptr) {
return;
}
NotificationReceiveDataWorker *dataWorker = new (std::nothrow) NotificationReceiveDataWorker();
if (dataWorker == nullptr) {
ANS_LOGE("null dataWorker");
return;
}
dataWorker->priorityEnable = callbackData->GetEnable();
dataWorker->type = Type::ENABLE_PRIORITY_CHANGED;
dataWorker->subscriber = std::static_pointer_cast<SubscriberInstance>(shared_from_this());
CallThreadSafeFunc(dataWorker);
}
void ThreadSafeOnEnabledPriorityByBundleChanged(napi_env env, napi_value jsCallback, void* context, void* data)
{
ANS_LOGD("called");
auto dataWorkerData = reinterpret_cast<NotificationReceiveDataWorker *>(data);
if (dataWorkerData == nullptr) {
ANS_LOGE("null dataWorkerData");
return;
}
auto subscriber = dataWorkerData->subscriber.lock();
if (subscriber == nullptr) {
ANS_LOGE("null subscriber");
return;
}
napi_value result = nullptr;
napi_handle_scope scope;
auto status = napi_open_handle_scope(env, &scope);
if (status != napi_ok || scope == nullptr) {
ANS_LOGE("status: %{public}d", status);
return;
}
napi_create_object(env, &result);
if (!Common::SetEnabledPriorityNotificationByBundleCallbackData(
env, dataWorkerData->priorityCallbackData, result)) {
result = Common::NapiGetNull(env);
}
Common::SetCallback(env, subscriber->GetCallbackInfo(ENABLE_PRIORITY_BY_BUNDLE_CHANGED).ref, result);
napi_close_handle_scope(env, scope);
}
void SubscriberInstance::OnEnabledPriorityByBundleChanged(
const std::shared_ptr<EnabledPriorityNotificationByBundleCallbackData> &callbackData)
{
ANS_LOGD("called");
if (enabledPriorityByBundleCallbackInfo_.ref == nullptr || enabledPriorityByBundleCallbackInfo_.env == nullptr) {
return;
}
if (callbackData == nullptr) {
ANS_LOGE("null callbackData");
return;
}
NotificationReceiveDataWorker *dataWorker = new (std::nothrow) NotificationReceiveDataWorker();
if (dataWorker == nullptr) {
ANS_LOGE("null dataWorker");
return;
}
dataWorker->priorityCallbackData = *callbackData;
dataWorker->type = Type::ENABLE_PRIORITY_BY_BUNDLE_CHANGED;
dataWorker->subscriber = std::static_pointer_cast<SubscriberInstance>(shared_from_this());
CallThreadSafeFunc(dataWorker);
}
void ThreadSafeOnSystemUpdate(napi_env env, napi_value jsCallback, void* context, void* data)
{
ANS_LOGD("called");
auto dataWorkerData = reinterpret_cast<NotificationReceiveDataWorker *>(data);
if (dataWorkerData == nullptr) {
ANS_LOGE("null dataWorkerData");
return;
}
auto subscriber = dataWorkerData->subscriber.lock();
if (subscriber == nullptr) {
ANS_LOGE("null subscriber");
return;
}
napi_value result = nullptr;
napi_handle_scope scope;
auto status = napi_open_handle_scope(env, &scope);
if (status != napi_ok || scope == nullptr) {
ANS_LOGE("status: %{public}d", status);
return;
}
napi_create_object(env, &result);
if (!SetSubscribeCallbackData(env, dataWorkerData->request, nullptr, NO_DELETE_REASON, result)) {
ANS_LOGE("Convert data to JS fail.");
} else {
Common::SetCallback(env, subscriber->GetCallbackInfo(SYSTEM_UPDATE).ref, result);
}
napi_close_handle_scope(env, scope);
}
void SubscriberInstance::OnSystemUpdate(const std::shared_ptr<OHOS::Notification::Notification> &request)
{
ANS_LOGD("called");
if (systemUpdateCallbackInfo_.ref == nullptr || systemUpdateCallbackInfo_.env == nullptr) {
return;
}
if (request == nullptr) {
ANS_LOGE("OnSystemUpdate fail, null request");
return;
}
NotificationReceiveDataWorker *dataWorker = new (std::nothrow) NotificationReceiveDataWorker();
if (dataWorker == nullptr) {
ANS_LOGE("null dataWorker");
return;
}
dataWorker->request = request;
dataWorker->type = Type::SYSTEM_UPDATE;
dataWorker->subscriber = std::static_pointer_cast<SubscriberInstance>(shared_from_this());
CallThreadSafeFunc(dataWorker);
}
void ThreadSafeOnBadgeChanged(napi_env env, napi_value jsCallback, void* context, void* data)
{
ANS_LOGD("called");
auto dataWorkerData = reinterpret_cast<NotificationReceiveDataWorker *>(data);
if (dataWorkerData == nullptr) {
ANS_LOGE("null dataWorkerData");
return;
}
auto subscriber = dataWorkerData->subscriber.lock();
if (subscriber == nullptr) {
ANS_LOGE("null subscriber");
return;
}
napi_value result = nullptr;
napi_handle_scope scope;
auto status = napi_open_handle_scope(env, &scope);
if (status != napi_ok || scope == nullptr) {
ANS_LOGE("status: %{public}d", status);
return;
}
napi_create_object(env, &result);
if (!Common::SetBadgeCallbackData(env, dataWorkerData->badge, result)) {
result = Common::NapiGetNull(env);
}
Common::SetCallback(env, subscriber->GetCallbackInfo(BADGE_CHANGED).ref, result);
napi_close_handle_scope(env, scope);
}
void SubscriberInstance::OnBadgeChanged(
const std::shared_ptr<BadgeNumberCallbackData> &badgeData)
{
ANS_LOGD("called");
if (setBadgeCallbackInfo_.ref == nullptr || setBadgeCallbackInfo_.env == nullptr) {
return;
}
if (badgeData == nullptr) {
ANS_LOGE("null badgeData");
return;
}
NotificationReceiveDataWorker *dataWorker = new (std::nothrow) NotificationReceiveDataWorker();
if (dataWorker == nullptr) {
ANS_LOGE("null dataWorker");
return;
}
ANS_LOGI("badgeChg %{public}s uid=%{public}d n=%{public}d",
badgeData->GetBundle().c_str(), badgeData->GetUid(), badgeData->GetBadgeNumber());
dataWorker->badge = *badgeData;
dataWorker->type = Type::BADGE_CHANGED;
dataWorker->subscriber = std::static_pointer_cast<SubscriberInstance>(shared_from_this());
CallThreadSafeFunc(dataWorker);
}
void ThreadSafeOnBadgeEnabledChanged(napi_env env, napi_value jsCallback, void* context, void* data)
{
ANS_LOGD("called");
auto dataWorkerData = reinterpret_cast<NotificationReceiveDataWorker *>(data);
if (dataWorkerData == nullptr) {
ANS_LOGE("null dataWorkerData");
return;
}
auto subscriber = dataWorkerData->subscriber.lock();
if (subscriber == nullptr) {
ANS_LOGE("null subscriber");
return;
}
napi_value result = nullptr;
napi_handle_scope scope;
auto status = napi_open_handle_scope(env, &scope);
if (status != napi_ok || scope == nullptr) {
ANS_LOGE("status: %{public}d", status);
return;
}
napi_create_object(env, &result);
if (!Common::SetEnabledNotificationCallbackData(env, dataWorkerData->callbackData, result)) {
result = Common::NapiGetNull(env);
}
Common::SetCallback(env, subscriber->GetCallbackInfo(BADGE_ENABLED_CHANGED).ref, result);
napi_close_handle_scope(env, scope);
}
void SubscriberInstance::OnBadgeEnabledChanged(
const sptr<EnabledNotificationCallbackData> &callbackData)
{
if (setBadgeEnabledCallbackInfo_.ref == nullptr) {
return;
}
if (callbackData == nullptr) {
ANS_LOGE("null callbackData");
return;
}
NotificationReceiveDataWorker *dataWorker = new (std::nothrow) NotificationReceiveDataWorker();
if (dataWorker == nullptr) {
ANS_LOGE("null dataWorker");
return;
}
dataWorker->callbackData = *callbackData;
dataWorker->type = Type::BADGE_ENABLED_CHANGED;
dataWorker->subscriber = std::static_pointer_cast<SubscriberInstance>(shared_from_this());
CallThreadSafeFunc(dataWorker);
}
void SubscriberInstance::SetThreadSafeFunction(const napi_threadsafe_function &tsfn)
{
std::lock_guard<ffrt::mutex> lock(tsfnMutex_);
tsfn_ = tsfn;
}
void SubscriberInstance::SetEnv(const napi_env &env)
{
env_ = env;
}
void SubscriberInstance::SetCancelCallbackInfo(const napi_env &env, const napi_ref &ref)
{
canceCallbackInfo_.env = env;
canceCallbackInfo_.ref = ref;
}
SubscriberInstance::CallbackInfo SubscriberInstance::GetCancelCallbackInfo()
{
return canceCallbackInfo_;
}
void SubscriberInstance::SetConsumeCallbackInfo(const napi_env &env, const napi_ref &ref)
{
consumeCallbackInfo_.env = env;
consumeCallbackInfo_.ref = ref;
}
SubscriberInstance::CallbackInfo SubscriberInstance::GetConsumeCallbackInfo()
{
return consumeCallbackInfo_;
}
void SubscriberInstance::SetUpdateCallbackInfo(const napi_env &env, const napi_ref &ref)
{
updateCallbackInfo_.env = env;
updateCallbackInfo_.ref = ref;
}
SubscriberInstance::CallbackInfo SubscriberInstance::GetUpdateCallbackInfo()
{
return updateCallbackInfo_;
}
void SubscriberInstance::SetSubscribeCallbackInfo(const napi_env &env, const napi_ref &ref)
{
subscribeCallbackInfo_.env = env;
subscribeCallbackInfo_.ref = ref;
}
SubscriberInstance::CallbackInfo SubscriberInstance::GetSubscribeCallbackInfo()
{
return subscribeCallbackInfo_;
}
void SubscriberInstance::SetUnsubscribeCallbackInfo(const napi_env &env, const napi_ref &ref)
{
unsubscribeCallbackInfo_.env = env;
unsubscribeCallbackInfo_.ref = ref;
}
SubscriberInstance::CallbackInfo SubscriberInstance::GetUnsubscribeCallbackInfo()
{
return unsubscribeCallbackInfo_;
}
void SubscriberInstance::SetDieCallbackInfo(const napi_env &env, const napi_ref &ref)
{
dieCallbackInfo_.env = env;
dieCallbackInfo_.ref = ref;
}
SubscriberInstance::CallbackInfo SubscriberInstance::GetDieCallbackInfo()
{
return dieCallbackInfo_;
}
void SubscriberInstance::SetDisturbModeCallbackInfo(const napi_env &env, const napi_ref &ref)
{
disturbModeCallbackInfo_.env = env;
disturbModeCallbackInfo_.ref = ref;
}
SubscriberInstance::CallbackInfo SubscriberInstance::GetDisturbModeCallbackInfo()
{
return disturbModeCallbackInfo_;
}
void SubscriberInstance::SetEnabledNotificationCallbackInfo(const napi_env &env, const napi_ref &ref)
{
enabledNotificationCallbackInfo_.env = env;
enabledNotificationCallbackInfo_.ref = ref;
}
SubscriberInstance::CallbackInfo SubscriberInstance::GetEnabledNotificationCallbackInfo()
{
return enabledNotificationCallbackInfo_;
}
void SubscriberInstance::SetEnabledSilentReminderCallbackInfo(const napi_env &env, const napi_ref &ref)
{
enabledSilentReminderCallbackInfo_.env = env;
enabledSilentReminderCallbackInfo_.ref = ref;
}
SubscriberInstance::CallbackInfo SubscriberInstance::GetEnabledSilentReminderCallbackInfo()
{
return enabledSilentReminderCallbackInfo_;
}
void SubscriberInstance::SetNotificationSwitchChangedCallbackInfo(const napi_env &env, const napi_ref &ref)
{
notificationSwitchChangedCallbackInfo_.env = env;
notificationSwitchChangedCallbackInfo_.ref = ref;
}
SubscriberInstance::CallbackInfo SubscriberInstance::GetNotificationSwitchChangedCallbackInfo()
{
return notificationSwitchChangedCallbackInfo_;
}
void SubscriberInstance::SetEnabledPriorityCallbackInfo(const napi_env &env, const napi_ref &ref)
{
enabledPriorityCallbackInfo_.env = env;
enabledPriorityCallbackInfo_.ref = ref;
}
SubscriberInstance::CallbackInfo SubscriberInstance::GetEnabledPriorityCallbackInfo()
{
return enabledPriorityCallbackInfo_;
}
void SubscriberInstance::SetEnabledPriorityByBundleCallbackInfo(const napi_env &env, const napi_ref &ref)
{
enabledPriorityByBundleCallbackInfo_.env = env;
enabledPriorityByBundleCallbackInfo_.ref = ref;
}
SubscriberInstance::CallbackInfo SubscriberInstance::GetEnabledPriorityByBundleCallbackInfo()
{
return enabledPriorityByBundleCallbackInfo_;
}
void SubscriberInstance::SetSystemUpdateCallbackInfo(const napi_env &env, const napi_ref &ref)
{
systemUpdateCallbackInfo_.env = env;
systemUpdateCallbackInfo_.ref = ref;
}
SubscriberInstance::CallbackInfo SubscriberInstance::GetSystemUpdateCallbackInfo()
{
return systemUpdateCallbackInfo_;
}
void SubscriberInstance::SetDisturbDateCallbackInfo(const napi_env &env, const napi_ref &ref)
{
disturbDateCallbackInfo_.env = env;
disturbDateCallbackInfo_.ref = ref;
}
SubscriberInstance::CallbackInfo SubscriberInstance::GetDisturbDateCallbackInfo()
{
return disturbDateCallbackInfo_;
}
void SubscriberInstance::SetDisturbChangedCallbackInfo(const napi_env &env, const napi_ref &ref)
{
disturbChangedCallbackInfo_.env = env;
disturbChangedCallbackInfo_.ref = ref;
}
SubscriberInstance::CallbackInfo SubscriberInstance::GetDisturbChangedCallbackInfo()
{
return disturbChangedCallbackInfo_;
}
void SubscriberInstance::SetBadgeCallbackInfo(const napi_env &env, const napi_ref &ref)
{
setBadgeCallbackInfo_.env = env;
setBadgeCallbackInfo_.ref = ref;
}
SubscriberInstance::CallbackInfo SubscriberInstance::GetBadgeCallbackInfo()
{
return setBadgeCallbackInfo_;
}
void SubscriberInstance::SetBadgeEnabledCallbackInfo(const napi_env &env, const napi_ref &ref)
{
setBadgeEnabledCallbackInfo_.env = env;
setBadgeEnabledCallbackInfo_.ref = ref;
}
SubscriberInstance::CallbackInfo SubscriberInstance::GetBadgeEnabledCallbackInfo()
{
return setBadgeEnabledCallbackInfo_;
}
void SubscriberInstance::SetBatchCancelCallbackInfo(const napi_env &env, const napi_ref &ref)
{
batchCancelCallbackInfo_.env = env;
batchCancelCallbackInfo_.ref = ref;
}
SubscriberInstance::CallbackInfo SubscriberInstance::GetBatchCancelCallbackInfo()
{
return batchCancelCallbackInfo_;
}
void SubscriberInstance::SetCallbackInfo(const napi_env &env, const std::string &type, const napi_ref &ref)
{
ANS_LOGI("subscriber set %{public}s callback", type.c_str());
if (type == CONSUME) {
SetConsumeCallbackInfo(env, ref);
} else if (type == CANCEL) {
SetCancelCallbackInfo(env, ref);
} else if (type == UPDATE) {
SetUpdateCallbackInfo(env, ref);
} else if (type == CONNECTED) {
SetSubscribeCallbackInfo(env, ref);
} else if (type == DIS_CONNECTED) {
SetUnsubscribeCallbackInfo(env, ref);
} else if (type == DIE) {
SetDieCallbackInfo(env, ref);
} else if (type == DISTURB_MODE_CHANGE) {
SetDisturbModeCallbackInfo(env, ref);
} else if (type == DISTURB_DATE_CHANGE) {
SetDisturbDateCallbackInfo(env, ref);
} else if (type == DISTURB_CHANGED) {
SetDisturbChangedCallbackInfo(env, ref);
} else if (type == ENABLE_NOTIFICATION_CHANGED) {
SetEnabledNotificationCallbackInfo(env, ref);
} else if (type == BADGE_CHANGED) {
SetBadgeCallbackInfo(env, ref);
} else if (type == BADGE_ENABLED_CHANGED) {
SetBadgeEnabledCallbackInfo(env, ref);
} else if (type == BATCH_CANCEL) {
SetBatchCancelCallbackInfo(env, ref);
} else if (type == ENABLE_PRIORITY_CHANGED) {
SetEnabledPriorityCallbackInfo(env, ref);
} else if (type == ENABLE_PRIORITY_BY_BUNDLE_CHANGED) {
SetEnabledPriorityByBundleCallbackInfo(env, ref);
} else if (type == SYSTEM_UPDATE) {
SetSystemUpdateCallbackInfo(env, ref);
} else if (type == ENABLE_SILENT_REMINDER_CHANGED) {
SetEnabledSilentReminderCallbackInfo(env, ref);
} else if (type == NOTIFICATION_SWITCH_CHANGED) {
SetNotificationSwitchChangedCallbackInfo(env, ref);
} else {
ANS_LOGW("type is error");
}
}
SubscriberInstance::CallbackInfo SubscriberInstance::GetCallbackInfo(const std::string &type)
{
if (type == CONSUME) {
return GetConsumeCallbackInfo();
} else if (type == CANCEL) {
return GetCancelCallbackInfo();
} else if (type == UPDATE) {
return GetUpdateCallbackInfo();
} else if (type == CONNECTED) {
return GetSubscribeCallbackInfo();
} else if (type == DIS_CONNECTED) {
return GetUnsubscribeCallbackInfo();
} else if (type == DIE) {
return GetDieCallbackInfo();
} else if (type == DISTURB_MODE_CHANGE) {
return GetDisturbModeCallbackInfo();
} else if (type == DISTURB_DATE_CHANGE) {
return GetDisturbDateCallbackInfo();
} else if (type == DISTURB_CHANGED) {
return GetDisturbChangedCallbackInfo();
} else if (type == ENABLE_NOTIFICATION_CHANGED) {
return GetEnabledNotificationCallbackInfo();
} else if (type == BADGE_CHANGED) {
return GetBadgeCallbackInfo();
} else if (type == BADGE_ENABLED_CHANGED) {
return GetBadgeEnabledCallbackInfo();
} else if (type == BATCH_CANCEL) {
return GetBatchCancelCallbackInfo();
} else if (type == ENABLE_PRIORITY_CHANGED) {
return GetEnabledPriorityCallbackInfo();
} else if (type == ENABLE_PRIORITY_BY_BUNDLE_CHANGED) {
return GetEnabledPriorityByBundleCallbackInfo();
} else if (type == SYSTEM_UPDATE) {
return GetSystemUpdateCallbackInfo();
} else if (type == ENABLE_SILENT_REMINDER_CHANGED) {
return GetEnabledSilentReminderCallbackInfo();
} else if (type == NOTIFICATION_SWITCH_CHANGED) {
return GetNotificationSwitchChangedCallbackInfo();
} else {
ANS_LOGW("type is error");
return {nullptr, nullptr};
}
}
bool HasNotificationSubscriber(const napi_env &env, const napi_value &value, SubscriberInstancesInfo &subscriberInfo)
{
std::lock_guard<ffrt::mutex> lock(mutex_);
for (auto vec : subscriberInstances_) {
napi_value callback = nullptr;
napi_get_reference_value(env, vec.ref, &callback);
if (value == nullptr || callback == nullptr) {
continue;
}
bool isEquals = false;
napi_strict_equals(env, value, callback, &isEquals);
if (isEquals) {
subscriberInfo = vec;
return true;
}
}
return false;
}
void ThreadFinished(napi_env env, void* data, [[maybe_unused]] void* context)
{
ANS_LOGD("called");
}
void SubThreadSafeCommon(napi_env env, napi_value jsCallback, void* context, void* data, Type type)
{
switch (type) {
case Type::ENABLE_PRIORITY_CHANGED:
ThreadSafeOnEnabledPriorityChanged(env, jsCallback, context, data);
break;
case Type::ENABLE_PRIORITY_BY_BUNDLE_CHANGED:
ThreadSafeOnEnabledPriorityByBundleChanged(env, jsCallback, context, data);
break;
case Type::SYSTEM_UPDATE:
ThreadSafeOnSystemUpdate(env, jsCallback, context, data);
break;
default:
break;
}
}
void ThreadSafeCommon(napi_env env, napi_value jsCallback, void* context, void* data)
{
ANS_LOGD("called");
auto dataWorkerData = reinterpret_cast<NotificationReceiveDataWorker *>(data);
switch (dataWorkerData->type) {
case Type::CANCEL:
ThreadSafeOnCancel(env, jsCallback, context, data);
break;
case Type::BATCH_CANCEL:
ThreadSafeOnBatchCancel(env, jsCallback, context, data);
break;
case Type::CONSUME:
ThreadSafeOnConsumed(env, jsCallback, context, data);
break;
case Type::UPDATE:
ThreadSafeOnUpdate(env, jsCallback, context, data);
break;
case Type::CONNECTED:
ThreadSafeOnConnected(env, jsCallback, context, data);
break;
case Type::DIS_CONNECTED:
ThreadSafeOnDisconnected(env, jsCallback, context, data);
break;
case Type::DIE:
ThreadSafeOnDestroy(env, jsCallback, context, data);
break;
case Type::DISTURB_DATE_CHANGE:
ThreadSafeOnDoNotDisturbDateChange(env, jsCallback, context, data);
break;
case Type::DISTURB_CHANGED:
ThreadSafeOnDoNotDisturbChanged(env, jsCallback, context, data);
break;
case Type::ENABLE_NOTIFICATION_CHANGED:
ThreadSafeOnEnabledNotificationChanged(env, jsCallback, context, data);
break;
case Type::BADGE_CHANGED:
ThreadSafeOnBadgeChanged(env, jsCallback, context, data);
break;
case Type::BADGE_ENABLED_CHANGED:
ThreadSafeOnBadgeEnabledChanged(env, jsCallback, context, data);
break;
case Type::ENABLE_SILENT_REMINDER_CHANGED:
ThreadSafeOnEnabledSilentReminderChanged(env, jsCallback, context, data);
break;
case Type::NOTIFICATION_SWITCH_CHANGED:
ThreadSafeOnNotificationSwitchChanged(env, jsCallback, context, data);
break;
default:
break;
}
SubThreadSafeCommon(env, jsCallback, context, data, dataWorkerData->type);
delete dataWorkerData;
dataWorkerData = nullptr;
}
napi_value GetNotificationSubscriber(
const napi_env &env, const napi_value &value, SubscriberInstancesInfo &subscriberInfo)
{
ANS_LOGD("called");
bool hasProperty = false;
napi_valuetype valuetype = napi_undefined;
napi_ref result = nullptr;
subscriberInfo.subscriber = std::make_shared<SubscriberInstance>();
if (subscriberInfo.subscriber == nullptr) {
ANS_LOGE("null subscriber");
std::string msg = "Mandatory parameters are left unspecified. subscriber is null";
Common::NapiThrowLegacy(env, ERROR_PARAM_INVALID, msg);
return nullptr;
}
struct SubscriberGuard {
const napi_env env;
SubscriberInstancesInfo &info;
bool active = true;
~SubscriberGuard()
{
if (active) {
info.subscriber->DeleteRef();
if (info.ref != nullptr) {
napi_delete_reference(env, info.ref);
info.ref = nullptr;
}
info.subscriber = nullptr;
}
}
} guard {env, subscriberInfo};
napi_create_reference(env, value, 1, &subscriberInfo.ref);
napi_value resourceName = nullptr;
napi_create_string_latin1(env, "tsfn", NAPI_AUTO_LENGTH, &resourceName);
napi_threadsafe_function tsfn = nullptr;
napi_create_threadsafe_function(env, nullptr, nullptr, resourceName, 0, 1, subscriberInfo.ref,
ThreadFinished, nullptr, ThreadSafeCommon, &tsfn);
subscriberInfo.subscriber->SetThreadSafeFunction(tsfn);
subscriberInfo.subscriber->SetEnv(env);
uint32_t subscribedFlag = NotificationConstant::SubscribedFlag::SUBSCRIBE_ON_DISCONNECTED;
NAPI_CALL(env, napi_has_named_property(env, value, "onConsume", &hasProperty));
if (hasProperty) {
napi_value nOnConsumed = nullptr;
napi_get_named_property(env, value, "onConsume", &nOnConsumed);
NAPI_CALL(env, napi_typeof(env, nOnConsumed, &valuetype));
if (valuetype != napi_function) {
ANS_LOGE("Wrong argument type. Function expected.");
std::string msg = "Incorrect parameter types.The type of param must be function.";
Common::NapiThrowLegacy(env, ERROR_PARAM_INVALID, msg);
return nullptr;
}
napi_create_reference(env, nOnConsumed, 1, &result);
subscriberInfo.subscriber->SetCallbackInfo(env, CONSUME, result);
subscribedFlag |= NotificationConstant::SubscribedFlag::SUBSCRIBE_ON_CONSUMED;
}
NAPI_CALL(env, napi_has_named_property(env, value, "onCancel", &hasProperty));
if (hasProperty) {
napi_value nOnCanceled = nullptr;
napi_get_named_property(env, value, "onCancel", &nOnCanceled);
NAPI_CALL(env, napi_typeof(env, nOnCanceled, &valuetype));
if (valuetype != napi_function) {
ANS_LOGE("Wrong argument type. Function expected.");
std::string msg = "Incorrect parameter types.The type of param must be function.";
Common::NapiThrowLegacy(env, ERROR_PARAM_INVALID, msg);
return nullptr;
}
napi_create_reference(env, nOnCanceled, 1, &result);
subscriberInfo.subscriber->SetCallbackInfo(env, CANCEL, result);
subscribedFlag |= NotificationConstant::SubscribedFlag::SUBSCRIBE_ON_CANCELED;
}
NAPI_CALL(env, napi_has_named_property(env, value, "onUpdate", &hasProperty));
if (hasProperty) {
napi_value nOnUpdate = nullptr;
napi_get_named_property(env, value, "onUpdate", &nOnUpdate);
NAPI_CALL(env, napi_typeof(env, nOnUpdate, &valuetype));
if (valuetype != napi_function) {
ANS_LOGE("Wrong argument type. Function expected.");
std::string msg = "Incorrect parameter types.The type of param must be function.";
Common::NapiThrowLegacy(env, ERROR_PARAM_INVALID, msg);
return nullptr;
}
napi_create_reference(env, nOnUpdate, 1, &result);
subscriberInfo.subscriber->SetCallbackInfo(env, UPDATE, result);
subscribedFlag |= NotificationConstant::SubscribedFlag::SUBSCRIBE_ON_UPDATE;
}
NAPI_CALL(env, napi_has_named_property(env, value, "onConnect", &hasProperty));
if (hasProperty) {
napi_value nOnConnected = nullptr;
napi_get_named_property(env, value, "onConnect", &nOnConnected);
NAPI_CALL(env, napi_typeof(env, nOnConnected, &valuetype));
if (valuetype != napi_function) {
ANS_LOGE("Wrong argument type. Function expected.");
std::string msg = "Incorrect parameter types.The type of param must be function.";
Common::NapiThrowLegacy(env, ERROR_PARAM_INVALID, msg);
return nullptr;
}
napi_create_reference(env, nOnConnected, 1, &result);
subscriberInfo.subscriber->SetCallbackInfo(env, CONNECTED, result);
subscribedFlag |= NotificationConstant::SubscribedFlag::SUBSCRIBE_ON_CONNECTED;
}
NAPI_CALL(env, napi_has_named_property(env, value, "onDisconnect", &hasProperty));
if (hasProperty) {
napi_value nOnDisConnect = nullptr;
napi_get_named_property(env, value, "onDisconnect", &nOnDisConnect);
NAPI_CALL(env, napi_typeof(env, nOnDisConnect, &valuetype));
if (valuetype != napi_function) {
ANS_LOGE("Wrong argument type. Function expected.");
std::string msg = "Incorrect parameter types.The type of param must be function.";
Common::NapiThrowLegacy(env, ERROR_PARAM_INVALID, msg);
return nullptr;
}
napi_create_reference(env, nOnDisConnect, 1, &result);
subscriberInfo.subscriber->SetCallbackInfo(env, DIS_CONNECTED, result);
subscribedFlag |= NotificationConstant::SubscribedFlag::SUBSCRIBE_ON_DISCONNECTED;
}
NAPI_CALL(env, napi_has_named_property(env, value, "onDestroy", &hasProperty));
if (hasProperty) {
napi_value nOnDied = nullptr;
napi_get_named_property(env, value, "onDestroy", &nOnDied);
NAPI_CALL(env, napi_typeof(env, nOnDied, &valuetype));
if (valuetype != napi_function) {
ANS_LOGE("Wrong argument type. Function expected.");
std::string msg = "Incorrect parameter types.The type of param must be function.";
Common::NapiThrowLegacy(env, ERROR_PARAM_INVALID, msg);
return nullptr;
}
napi_create_reference(env, nOnDied, 1, &result);
subscriberInfo.subscriber->SetCallbackInfo(env, DIE, result);
subscribedFlag |= NotificationConstant::SubscribedFlag::SUBSCRIBE_ON_DIED;
}
NAPI_CALL(env, napi_has_named_property(env, value, "onDisturbModeChange", &hasProperty));
if (hasProperty) {
napi_value nOnDisturbModeChanged = nullptr;
napi_get_named_property(env, value, "onDisturbModeChange", &nOnDisturbModeChanged);
NAPI_CALL(env, napi_typeof(env, nOnDisturbModeChanged, &valuetype));
if (valuetype != napi_function) {
ANS_LOGE("Wrong argument type. Function expected.");
std::string msg = "Incorrect parameter types.The type of param must be function.";
Common::NapiThrowLegacy(env, ERROR_PARAM_INVALID, msg);
return nullptr;
}
napi_create_reference(env, nOnDisturbModeChanged, 1, &result);
subscriberInfo.subscriber->SetCallbackInfo(env, DISTURB_MODE_CHANGE, result);
}
NAPI_CALL(env, napi_has_named_property(env, value, "onDoNotDisturbDateChange", &hasProperty));
if (hasProperty) {
napi_value nOnDisturbDateChanged = nullptr;
napi_get_named_property(env, value, "onDoNotDisturbDateChange", &nOnDisturbDateChanged);
NAPI_CALL(env, napi_typeof(env, nOnDisturbDateChanged, &valuetype));
if (valuetype != napi_function) {
ANS_LOGE("Wrong argument type. Function expected.");
std::string msg = "Incorrect parameter types.The type of param must be function.";
Common::NapiThrowLegacy(env, ERROR_PARAM_INVALID, msg);
return nullptr;
}
napi_create_reference(env, nOnDisturbDateChanged, 1, &result);
subscriberInfo.subscriber->SetCallbackInfo(env, DISTURB_DATE_CHANGE, result);
subscribedFlag |= NotificationConstant::SubscribedFlag::SUBSCRIBE_ON_DONOTDISTURBDATA_CHANGED;
}
NAPI_CALL(env, napi_has_named_property(env, value, "onDoNotDisturbChanged", &hasProperty));
if (hasProperty) {
napi_value nOnDoNotDisturbChanged = nullptr;
napi_get_named_property(env, value, "onDoNotDisturbChanged", &nOnDoNotDisturbChanged);
NAPI_CALL(env, napi_typeof(env, nOnDoNotDisturbChanged, &valuetype));
if (valuetype != napi_function) {
ANS_LOGE("Wrong argument type. Function expected.");
std::string msg = "Incorrect parameter types.The type of param must be function.";
Common::NapiThrowLegacy(env, ERROR_PARAM_INVALID, msg);
return nullptr;
}
napi_create_reference(env, nOnDoNotDisturbChanged, 1, &result);
subscriberInfo.subscriber->SetCallbackInfo(env, DISTURB_CHANGED, result);
subscribedFlag |= NotificationConstant::SubscribedFlag::SUBSCRIBE_ON_DONOTDISTURBDATA_CHANGED;
}
NAPI_CALL(env, napi_has_named_property(env, value, "onEnabledNotificationChanged", &hasProperty));
if (hasProperty) {
napi_value nOnEnabledNotificationChanged = nullptr;
napi_get_named_property(env, value, "onEnabledNotificationChanged", &nOnEnabledNotificationChanged);
NAPI_CALL(env, napi_typeof(env, nOnEnabledNotificationChanged, &valuetype));
if (valuetype != napi_function) {
ANS_LOGE("Wrong argument type. Function expected.");
std::string msg = "Incorrect parameter types.The type of param must be function.";
Common::NapiThrowLegacy(env, ERROR_PARAM_INVALID, msg);
return nullptr;
}
napi_create_reference(env, nOnEnabledNotificationChanged, 1, &result);
subscriberInfo.subscriber->SetCallbackInfo(env, ENABLE_NOTIFICATION_CHANGED, result);
subscribedFlag |= NotificationConstant::SubscribedFlag::SUBSCRIBE_ON_ENABLENOTIFICATION_CHANGED;
}
NAPI_CALL(env, napi_has_named_property(env, value, "onEnabledSilentReminderChanged", &hasProperty));
if (hasProperty) {
napi_value nOnEnabledSilentReminderChanged = nullptr;
napi_get_named_property(env, value, "onEnabledSilentReminderChanged", &nOnEnabledSilentReminderChanged);
NAPI_CALL(env, napi_typeof(env, nOnEnabledSilentReminderChanged, &valuetype));
if (valuetype != napi_function) {
ANS_LOGE("Wrong argument type. Function expected.");
std::string msg = "Incorrect parameter types.The type of param must be function.";
Common::NapiThrowLegacy(env, ERROR_PARAM_INVALID, msg);
return nullptr;
}
napi_create_reference(env, nOnEnabledSilentReminderChanged, 1, &result);
subscriberInfo.subscriber->SetCallbackInfo(env, ENABLE_SILENT_REMINDER_CHANGED, result);
subscribedFlag |= NotificationConstant::SubscribedFlag::SUBSCRIBE_ON_ENABLEDSILENTREMINDER_CHANGED;
}
NAPI_CALL(env, napi_has_named_property(env, value, "onNotificationSwitchChanged", &hasProperty));
if (hasProperty) {
napi_value nOnNotificationSwitchChanged = nullptr;
napi_get_named_property(env, value, "onNotificationSwitchChanged", &nOnNotificationSwitchChanged);
NAPI_CALL(env, napi_typeof(env, nOnNotificationSwitchChanged, &valuetype));
if (valuetype != napi_function) {
ANS_LOGE("Wrong argument type. Function expected.");
std::string msg = "Incorrect parameter types.The type of param must be function.";
Common::NapiThrowLegacy(env, ERROR_PARAM_INVALID, msg);
return nullptr;
}
napi_create_reference(env, nOnNotificationSwitchChanged, 1, &result);
subscriberInfo.subscriber->SetCallbackInfo(env, NOTIFICATION_SWITCH_CHANGED, result);
subscribedFlag |= NotificationConstant::SubscribedFlag::SUBSCRIBE_ON_NOTIFICATION_SWITCH_CHANGED;
}
NAPI_CALL(env, napi_has_named_property(env, value, "onEnabledPriorityChanged", &hasProperty));
if (hasProperty) {
napi_value nOnEnabledPriorityChanged = nullptr;
napi_get_named_property(env, value, "onEnabledPriorityChanged", &nOnEnabledPriorityChanged);
NAPI_CALL(env, napi_typeof(env, nOnEnabledPriorityChanged, &valuetype));
if (valuetype != napi_function) {
ANS_LOGE("Wrong argument type. Function expected.");
std::string msg = "Incorrect parameter types.The type of param must be function.";
Common::NapiThrowLegacy(env, ERROR_PARAM_INVALID, msg);
return nullptr;
}
napi_create_reference(env, nOnEnabledPriorityChanged, 1, &result);
subscriberInfo.subscriber->SetCallbackInfo(env, ENABLE_PRIORITY_CHANGED, result);
subscribedFlag |= NotificationConstant::SubscribedFlag::SUBSCRIBE_ON_ENABLEPRIORITY_CHANGED;
}
NAPI_CALL(env, napi_has_named_property(env, value, "onEnabledPriorityByBundleChanged", &hasProperty));
if (hasProperty) {
napi_value nOnEnabledPriorityByBundleChanged = nullptr;
napi_get_named_property(env, value, "onEnabledPriorityByBundleChanged", &nOnEnabledPriorityByBundleChanged);
NAPI_CALL(env, napi_typeof(env, nOnEnabledPriorityByBundleChanged, &valuetype));
if (valuetype != napi_function) {
ANS_LOGE("Wrong argument type. Function expected.");
std::string msg = "Incorrect parameter types.The type of param must be function.";
Common::NapiThrowLegacy(env, ERROR_PARAM_INVALID, msg);
return nullptr;
}
napi_create_reference(env, nOnEnabledPriorityByBundleChanged, 1, &result);
subscriberInfo.subscriber->SetCallbackInfo(env, ENABLE_PRIORITY_BY_BUNDLE_CHANGED, result);
subscribedFlag |= NotificationConstant::SubscribedFlag::SUBSCRIBE_ON_ENABLEPRIORITYBYBUNDLE_CHANGED;
}
NAPI_CALL(env, napi_has_named_property(env, value, "onSystemUpdate", &hasProperty));
if (hasProperty) {
napi_value nOnSystemUpdate = nullptr;
napi_get_named_property(env, value, "onSystemUpdate", &nOnSystemUpdate);
NAPI_CALL(env, napi_typeof(env, nOnSystemUpdate, &valuetype));
if (valuetype != napi_function) {
ANS_LOGE("Wrong argument type. Function expected.");
std::string msg = "Incorrect parameter types.The type of param must be function.";
Common::NapiThrowLegacy(env, ERROR_PARAM_INVALID, msg);
return nullptr;
}
napi_create_reference(env, nOnSystemUpdate, 1, &result);
subscriberInfo.subscriber->SetCallbackInfo(env, SYSTEM_UPDATE, result);
subscribedFlag |= NotificationConstant::SubscribedFlag::SUBSCRIBE_ON_SYSTEM_UPDATE;
}
NAPI_CALL(env, napi_has_named_property(env, value, "onBadgeChanged", &hasProperty));
if (hasProperty) {
napi_value nOnBadgeChanged = nullptr;
napi_get_named_property(env, value, "onBadgeChanged", &nOnBadgeChanged);
NAPI_CALL(env, napi_typeof(env, nOnBadgeChanged, &valuetype));
if (valuetype != napi_function) {
ANS_LOGE("Wrong argument type. Function expected.");
std::string msg = "Incorrect parameter types.The type of param must be function.";
Common::NapiThrowLegacy(env, ERROR_PARAM_INVALID, msg);
return nullptr;
}
napi_create_reference(env, nOnBadgeChanged, 1, &result);
subscriberInfo.subscriber->SetCallbackInfo(env, BADGE_CHANGED, result);
subscribedFlag |= NotificationConstant::SubscribedFlag::SUBSCRIBE_ON_BADGE_CHANGED;
}
NAPI_CALL(env, napi_has_named_property(env, value, "onBadgeEnabledChanged", &hasProperty));
if (hasProperty) {
napi_value nOnBadgeEnabledChanged = nullptr;
napi_get_named_property(env, value, "onBadgeEnabledChanged", &nOnBadgeEnabledChanged);
NAPI_CALL(env, napi_typeof(env, nOnBadgeEnabledChanged, &valuetype));
if (valuetype != napi_function) {
ANS_LOGE("Wrong argument type. Function expected.");
std::string msg = "Incorrect parameter types.The type of param must be function.";
Common::NapiThrowLegacy(env, ERROR_PARAM_INVALID, msg);
return nullptr;
}
napi_create_reference(env, nOnBadgeEnabledChanged, 1, &result);
subscriberInfo.subscriber->SetCallbackInfo(env, BADGE_ENABLED_CHANGED, result);
subscribedFlag |= NotificationConstant::SubscribedFlag::SUBSCRIBE_ON_BADGEENABLE_CHANGED;
}
NAPI_CALL(env, napi_has_named_property(env, value, "onBatchCancel", &hasProperty));
if (hasProperty) {
napi_value onBatchCancel = nullptr;
napi_get_named_property(env, value, "onBatchCancel", &onBatchCancel);
NAPI_CALL(env, napi_typeof(env, onBatchCancel, &valuetype));
if (valuetype != napi_function) {
ANS_LOGE("Wrong argument type. Function expected.");
std::string msg = "Incorrect parameter types.The type of param must be function.";
Common::NapiThrowLegacy(env, ERROR_PARAM_INVALID, msg);
return nullptr;
}
napi_create_reference(env, onBatchCancel, 1, &result);
subscriberInfo.subscriber->SetCallbackInfo(env, BATCH_CANCEL, result);
subscribedFlag |= NotificationConstant::SubscribedFlag::SUBSCRIBE_ON_BATCHCANCELED;
}
subscriberInfo.subscriber->SetSubscribedFlags(subscribedFlag);
guard.active = false;
return Common::NapiGetNull(env);
}
bool AddSubscriberInstancesInfo(const napi_env &env, const SubscriberInstancesInfo &subscriberInfo)
{
ANS_LOGD("called");
if (subscriberInfo.ref == nullptr) {
ANS_LOGE("null ref");
return false;
}
if (subscriberInfo.subscriber == nullptr) {
ANS_LOGE("null subscriber");
return false;
}
std::lock_guard<ffrt::mutex> lock(mutex_);
subscriberInstances_.emplace_back(subscriberInfo);
return true;
}
bool DelSubscriberInstancesInfo(const napi_env &env, const std::shared_ptr<SubscriberInstance> subscriber)
{
ANS_LOGD("called");
if (subscriber == nullptr) {
ANS_LOGE("null subscriber");
return false;
}
std::lock_guard<ffrt::mutex> lock(mutex_);
for (auto it = subscriberInstances_.begin(); it != subscriberInstances_.end(); ++it) {
if (it->subscriber == subscriber) {
DelDeletingSubscriber(it->subscriber);
napi_delete_reference(env, it->ref);
subscriber->DeleteRef();
subscriberInstances_.erase(it);
return true;
}
}
return false;
}
napi_value ParseParameters(const napi_env &env, const napi_callback_info &info,
NotificationSubscribeInfo &subscriberInfo, std::shared_ptr<SubscriberInstance> &subscriber, napi_ref &callback)
{
size_t argc = SUBSCRIBE_MAX_PARA;
napi_value argv[SUBSCRIBE_MAX_PARA] = {nullptr};
napi_value thisVar = nullptr;
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
if (argc < 1) {
ANS_LOGE("Wrong number of arguments");
Common::NapiThrowLegacy(env, ERROR_PARAM_INVALID, MANDATORY_PARAMETER_ARE_LEFT_UNSPECIFIED);
return nullptr;
}
napi_valuetype valuetype = napi_undefined;
NAPI_CALL(env, napi_typeof(env, argv[PARAM0], &valuetype));
if (valuetype != napi_object) {
ANS_LOGE("Wrong argument type for arg0. NotificationSubscriber object expected.");
std::string msg = "Incorrect parameter types.The type of param must be NotificationSubscriber.";
Common::NapiThrowLegacy(env, ERROR_PARAM_INVALID, msg);
return nullptr;
}
SubscriberInstancesInfo subscriberInstancesInfo;
if (!HasNotificationSubscriber(env, argv[PARAM0], subscriberInstancesInfo)) {
if (GetNotificationSubscriber(env, argv[PARAM0], subscriberInstancesInfo) == nullptr) {
ANS_LOGE("NotificationSubscriber parse failed");
return nullptr;
}
if (!AddSubscriberInstancesInfo(env, subscriberInstancesInfo)) {
ANS_LOGE("AddSubscriberInstancesInfo add failed");
subscriberInstancesInfo.subscriber->DeleteRef();
if (subscriberInstancesInfo.ref != nullptr) {
napi_delete_reference(env, subscriberInstancesInfo.ref);
subscriberInstancesInfo.ref = nullptr;
}
subscriberInstancesInfo.subscriber = nullptr;
return nullptr;
}
}
subscriber = subscriberInstancesInfo.subscriber;
if (argc >= SUBSCRIBE_MAX_PARA - 1) {
NAPI_CALL(env, napi_typeof(env, argv[PARAM1], &valuetype));
if ((valuetype != napi_function) && (valuetype != napi_object)) {
ANS_LOGE("Wrong argument type for arg1."
"Function or NotificationSubscribeInfo object expected. Excute promise");
return Common::NapiGetNull(env);
}
if (valuetype == napi_function) {
napi_create_reference(env, argv[PARAM1], 1, &callback);
} else {
if (Common::GetNotificationSubscriberInfo(env, argv[PARAM1], subscriberInfo) == nullptr) {
ANS_LOGE("NotificationSubscribeInfo parse failed");
return nullptr;
}
}
}
if (argc >= SUBSCRIBE_MAX_PARA) {
NAPI_CALL(env, napi_typeof(env, argv[PARAM2], &valuetype));
if (valuetype != napi_function) {
ANS_LOGE("Callback is not function enforce promise.");
return Common::NapiGetNull(env);
}
napi_create_reference(env, argv[PARAM2], 1, &callback);
}
return Common::NapiGetNull(env);
}
napi_value ParseParameters(const napi_env &env, const napi_callback_info &info,
NotificationSubscribeInfo &subscriberInfo, std::shared_ptr<SubscriberInstance> &subscriber)
{
size_t argc = SUBSCRIBE_NOTIFICATION_MAX_PARA;
napi_value argv[SUBSCRIBE_NOTIFICATION_MAX_PARA] = {nullptr};
napi_value thisVar = nullptr;
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
if (argc < 1) {
ANS_LOGE("Wrong number of arguments");
return nullptr;
}
napi_valuetype valuetype = napi_undefined;
NAPI_CALL(env, napi_typeof(env, argv[PARAM0], &valuetype));
if (valuetype != napi_object) {
ANS_LOGE("Wrong argument type for arg0. NotificationSubscriber object expected.");
return nullptr;
}
SubscriberInstancesInfo subscriberInstancesInfo;
if (!HasNotificationSubscriber(env, argv[PARAM0], subscriberInstancesInfo)) {
if (GetNotificationSubscriber(env, argv[PARAM0], subscriberInstancesInfo) == nullptr) {
ANS_LOGE("NotificationSubscriber parse failed");
return nullptr;
}
if (!AddSubscriberInstancesInfo(env, subscriberInstancesInfo)) {
ANS_LOGE("AddSubscriberInstancesInfo add failed");
subscriberInstancesInfo.subscriber->DeleteRef();
if (subscriberInstancesInfo.ref != nullptr) {
napi_delete_reference(env, subscriberInstancesInfo.ref);
subscriberInstancesInfo.ref = nullptr;
}
subscriberInstancesInfo.subscriber = nullptr;
return nullptr;
}
}
subscriber = subscriberInstancesInfo.subscriber;
if (argc >= SUBSCRIBE_NOTIFICATION_MAX_PARA) {
NAPI_CALL(env, napi_typeof(env, argv[PARAM1], &valuetype));
if ((valuetype != napi_object)) {
ANS_LOGE("Wrong argument type for arg1. NotificationSubscriber object expected.");
return nullptr;
}
if (Common::GetNotificationSubscriberInfo(env, argv[PARAM1], subscriberInfo) == nullptr) {
ANS_LOGE("NotificationSubscribeInfo parse failed");
return nullptr;
}
}
return Common::NapiGetNull(env);
}
napi_value Subscribe(napi_env env, napi_callback_info info)
{
ANS_LOGD("called");
napi_ref callback = nullptr;
std::shared_ptr<SubscriberInstance> objectInfo = nullptr;
NotificationSubscribeInfo subscriberInfo;
if (ParseParameters(env, info, subscriberInfo, objectInfo, callback) == nullptr) {
ANS_LOGD("null ParseParameters");
return Common::NapiGetUndefined(env);
}
AsyncCallbackInfoSubscribe *asynccallbackinfo = new (std::nothrow) AsyncCallbackInfoSubscribe {
.env = env, .asyncWork = nullptr, .objectInfo = objectInfo, .subscriberInfo = subscriberInfo
};
if (!asynccallbackinfo) {
ANS_LOGD("null asynccallbackinfo");
return Common::JSParaError(env, callback);
}
napi_value promise = nullptr;
Common::PaddingCallbackPromiseInfo(env, callback, asynccallbackinfo->info, promise);
ANS_LOGD("Create subscribeNotification string.");
napi_value resourceName = nullptr;
napi_create_string_latin1(env, "subscribeNotification", NAPI_AUTO_LENGTH, &resourceName);
napi_status status = napi_create_async_work(env,
nullptr,
resourceName,
[](napi_env env, void *data) {
ANS_LOGD("Subscribe work excuted.");
if (!data) {
ANS_LOGE("Invalid asynccallbackinfo!");
return;
}
auto asynccallbackinfo = reinterpret_cast<AsyncCallbackInfoSubscribe *>(data);
if (asynccallbackinfo) {
if (asynccallbackinfo->subscriberInfo.hasSubscribeInfo) {
ANS_LOGD("Subscribe with NotificationSubscribeInfo excute.");
OHOS::Notification::NotificationSubscribeInfo subscribeInfo;
subscribeInfo.AddAppNames(asynccallbackinfo->subscriberInfo.bundleNames);
subscribeInfo.AddAppUserId(asynccallbackinfo->subscriberInfo.userId);
subscribeInfo.SetEnableClassification(asynccallbackinfo->subscriberInfo.enableClassification);
subscribeInfo.SetNeedSilentReplayOnSubscribe(
asynccallbackinfo->subscriberInfo.needSilentReplayOnSubscribe);
asynccallbackinfo->info.errorCode =
NotificationHelper::SubscribeNotification(*(asynccallbackinfo->objectInfo), subscribeInfo);
} else {
ANS_LOGD("SubscribeNotification execute.");
asynccallbackinfo->info.errorCode =
NotificationHelper::SubscribeNotification(*(asynccallbackinfo->objectInfo));
}
}
},
[](napi_env env, napi_status status, void *data) {
ANS_LOGD("Subscribe work complete.");
if (!data) {
ANS_LOGE("null data");
return;
}
auto asynccallbackinfo = reinterpret_cast<AsyncCallbackInfoSubscribe *>(data);
if (asynccallbackinfo) {
Common::ReturnCallbackPromise(env, asynccallbackinfo->info, Common::NapiGetNull(env));
if (asynccallbackinfo->info.callback != nullptr) {
ANS_LOGD("Delete subscribe callback reference.");
napi_delete_reference(env, asynccallbackinfo->info.callback);
}
napi_delete_async_work(env, asynccallbackinfo->asyncWork);
delete asynccallbackinfo;
asynccallbackinfo = nullptr;
}
ANS_LOGD("Subscribe work complete end.");
},
(void *)asynccallbackinfo,
&asynccallbackinfo->asyncWork);
if (status != napi_ok) {
ANS_LOGE("Create subscribeNotification async work failed.");
asynccallbackinfo->info.errorCode = ERR_ANS_INNER_TASK_ERR;
Common::CreateReturnValue(env, asynccallbackinfo->info, Common::NapiGetNull(env));
bool isCallback = asynccallbackinfo->info.isCallback;
if (asynccallbackinfo->info.callback != nullptr) {
napi_delete_reference(env, asynccallbackinfo->info.callback);
}
delete asynccallbackinfo;
asynccallbackinfo = nullptr;
return isCallback ? Common::NapiGetNull(env) : promise;
}
napi_add_env_cleanup_hook(env, ClearEnvCallback, objectInfo.get());
status = napi_queue_async_work_with_qos(env, asynccallbackinfo->asyncWork, napi_qos_user_initiated);
if (status != napi_ok) {
ANS_LOGE("Queue subscribeNotification async work failed.");
asynccallbackinfo->info.errorCode = ERR_ANS_INNER_TASK_ERR;
Common::CreateReturnValue(env, asynccallbackinfo->info, Common::NapiGetNull(env));
bool isCallback = asynccallbackinfo->info.isCallback;
if (asynccallbackinfo->info.callback != nullptr) {
napi_delete_reference(env, asynccallbackinfo->info.callback);
}
napi_delete_async_work(env, asynccallbackinfo->asyncWork);
delete asynccallbackinfo;
asynccallbackinfo = nullptr;
return isCallback ? Common::NapiGetNull(env) : promise;
}
if (asynccallbackinfo->info.isCallback) {
ANS_LOGD("null isCallback");
return Common::NapiGetNull(env);
} else {
return promise;
}
}
bool AddDeletingSubscriber(std::shared_ptr<SubscriberInstance> subscriber)
{
std::lock_guard<ffrt::mutex> lock(delMutex_);
auto iter = std::find(DeletingSubscriber.begin(), DeletingSubscriber.end(), subscriber);
if (iter != DeletingSubscriber.end()) {
return false;
}
DeletingSubscriber.push_back(subscriber);
return true;
}
void DelDeletingSubscriber(std::shared_ptr<SubscriberInstance> subscriber)
{
std::lock_guard<ffrt::mutex> lock(delMutex_);
auto iter = std::find(DeletingSubscriber.begin(), DeletingSubscriber.end(), subscriber);
if (iter != DeletingSubscriber.end()) {
DeletingSubscriber.erase(iter);
}
}
napi_value GetParamOperationInfoSub(const napi_env &env, const napi_value &content, OperationInfo& operationInfo)
{
napi_valuetype valuetype = napi_undefined;
napi_value result = nullptr;
bool hasProperty = false;
NAPI_CALL(env, napi_has_named_property(env, content, "operationType", &hasProperty));
if (hasProperty) {
napi_get_named_property(env, content, "operationType", &result);
NAPI_CALL(env, napi_typeof(env, result, &valuetype));
if (valuetype != napi_number) {
return nullptr;
}
int32_t code;
NAPI_CALL(env, napi_get_value_int32(env, result, &code));
operationInfo.operationType = code;
}
NAPI_CALL(env, napi_has_named_property(env, content, "buttonIndex", &hasProperty));
if (hasProperty) {
napi_get_named_property(env, content, "buttonIndex", &result);
NAPI_CALL(env, napi_typeof(env, result, &valuetype));
if (valuetype != napi_number) {
return nullptr;
}
int32_t code;
NAPI_CALL(env, napi_get_value_int32(env, result, &code));
operationInfo.btnIndex = code;
}
return Common::NapiGetNull(env);
}
napi_value GetParamOperationInfo(const napi_env &env, const napi_value &content, OperationInfo& operationInfo)
{
operationInfo.withOperationInfo = true;
napi_valuetype valuetype = napi_undefined;
NAPI_CALL(env, napi_typeof(env, content, &valuetype));
if (valuetype != napi_object) {
ANS_LOGE("Wrong argument type for arg1. object expected.");
std::string msg = "Incorrect parameter type. The type of operationInfo must be object.";
Common::NapiThrowLegacy(env, ERROR_PARAM_INVALID, msg);
return nullptr;
}
size_t strLen = 0;
napi_value result = nullptr;
bool hasProperty = false;
NAPI_CALL(env, napi_has_named_property(env, content, "actionName", &hasProperty));
if (hasProperty) {
napi_get_named_property(env, content, "actionName", &result);
NAPI_CALL(env, napi_typeof(env, result, &valuetype));
if (valuetype != napi_string) {
ANS_LOGE("Wrong argument type. String expected.");
std::string msg = "Incorrect parameter types. The type of actionName must be string.";
Common::NapiThrowLegacy(env, ERROR_PARAM_INVALID, msg);
return nullptr;
}
char str[STR_MAX_SIZE] = {0};
NAPI_CALL(env, napi_get_value_string_utf8(env, result, str, STR_MAX_SIZE - 1, &strLen));
operationInfo.actionName = str;
}
NAPI_CALL(env, napi_has_named_property(env, content, "userInput", &hasProperty));
if (hasProperty) {
napi_get_named_property(env, content, "userInput", &result);
NAPI_CALL(env, napi_typeof(env, result, &valuetype));
if (valuetype != napi_string) {
ANS_LOGE("Wrong argument type. String expected.");
std::string msg = "Incorrect parameter types. The type of userInput must be string.";
Common::NapiThrowLegacy(env, ERROR_PARAM_INVALID, msg);
return nullptr;
}
char str[LONG_STR_MAX_SIZE] = {0};
NAPI_CALL(env, napi_get_value_string_utf8(env, result, str, LONG_STR_MAX_SIZE - 1, &strLen));
operationInfo.userInput = str;
}
if (!operationInfo.userInput.empty()) {
return Common::NapiGetNull(env);
}
return GetParamOperationInfoSub(env, content, operationInfo);
}
napi_value ParseParameters(const napi_env &env, const napi_callback_info &info, std::string &hashCode,
napi_value& thisVar, OperationInfo& operationInfo)
{
ANS_LOGD("called");
size_t argc = DISTRIBUTE_REPLY_PARA;
napi_value argv[DISTRIBUTE_REPLY_PARA] = {nullptr};
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
if (argc < DISTRIBUTE_JUMP_PARA) {
ANS_LOGE("Wrong number of arguments");
Common::NapiThrowLegacy(env, ERROR_PARAM_INVALID, MANDATORY_PARAMETER_ARE_LEFT_UNSPECIFIED);
return nullptr;
}
napi_valuetype valuetype = napi_undefined;
NAPI_CALL(env, napi_typeof(env, argv[PARAM0], &valuetype));
if (valuetype == napi_string) {
size_t strLen = 0;
char str[STR_MAX_SIZE] = {0};
NAPI_CALL(env, napi_get_value_string_utf8(env, argv[PARAM0], str, STR_MAX_SIZE - 1, &strLen));
hashCode = str;
} else {
ANS_LOGE("Wrong argument type for arg0. string expected.");
std::string msg = "Incorrect parameter type. The type of hashcode must be string.";
Common::NapiThrowLegacy(env, ERROR_PARAM_INVALID, msg);
return nullptr;
}
if (hashCode.empty()) {
ANS_LOGE("Wrong argument type for arg0. not empty expected.");
std::string msg = "Incorrect parameter type. The type of hashcode must be not null.";
Common::NapiThrowLegacy(env, ERROR_PARAM_INVALID, msg);
return nullptr;
}
if (argc > DISTRIBUTE_JUMP_PARA) {
if (GetParamOperationInfo(env, argv[PARAM1], operationInfo) == nullptr) {
return Common::NapiGetUndefined(env);
}
}
return Common::NapiGetNull(env);
}
}
}