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 #define LOG_TAG "DataLoadParamsNapi"
16 #include "data_load_params_napi.h"
17
18 #include "logger.h"
19 #include "napi_data_utils.h"
20 #include "unified_data_napi.h"
21 #include "udmf_client.h"
22 #include "udmf_utils.h"
23
24 namespace OHOS {
25 namespace UDMF {
26 ConcurrentMap<std::string, napi_threadsafe_function> DataLoadParamsNapi::tsfns_;
27
Convert2NativeValue(napi_env env,napi_value in,DataLoadParams & dataLoadParams)28 bool DataLoadParamsNapi::Convert2NativeValue(napi_env env, napi_value in, DataLoadParams &dataLoadParams)
29 {
30 napi_value jsDataLoadInfo = nullptr;
31 NAPI_CALL_BASE(env, napi_get_named_property(env, in, "dataLoadInfo", &jsDataLoadInfo), false);
32 NAPI_CALL_BASE(env, NapiDataUtils::GetValue(env, jsDataLoadInfo, dataLoadParams.dataLoadInfo), false);
33 napi_value jsLoadHandler = nullptr;
34 NAPI_CALL_BASE(env, napi_get_named_property(env, in, "loadHandler", &jsLoadHandler), false);
35 dataLoadParams.dataLoadInfo.sequenceKey = UTILS::GenerateId();
36 tsfns_.Compute(dataLoadParams.dataLoadInfo.sequenceKey, [&](const std::string &k, napi_threadsafe_function &tsfn) {
37 if (tsfn != nullptr) {
38 LOG_WARN(UDMF_KITS_NAPI, "Listener has existed!");
39 napi_release_threadsafe_function(tsfn, napi_tsfn_release);
40 tsfn = nullptr;
41 }
42 napi_value workName;
43 napi_create_string_utf8(env, "threadsafe_function", NAPI_AUTO_LENGTH, &workName);
44 auto status = napi_create_threadsafe_function(env, jsLoadHandler, nullptr, workName, 0, 1, nullptr,
45 nullptr, nullptr, CallDataLoadHandler, &tsfn);
46 if (status != napi_ok) {
47 LOG_ERROR(UDMF_KITS_NAPI, "napi_create_threadsafe_function failed, status=%{public}d", status);
48 return false;
49 }
50 return true;
51 });
52 dataLoadParams.loadHandler = [](const std::string &udKey, const DataLoadInfo &dataLoadInfo) {
53 LOG_INFO(UDMF_KITS_NAPI, "Load handler Start.");
54 auto seqKey = UTILS::GetSequenceKey(udKey);
55 if (seqKey.empty()) {
56 LOG_ERROR(UDMF_KITS_NAPI, "Error udKey:%{public}s", udKey.c_str());
57 return;
58 }
59 bool tsfnExist = tsfns_.ComputeIfPresent(seqKey, [&](const std::string &key, napi_threadsafe_function &tsfn) {
60 DataLoadArgs *infoArgs = new (std::nothrow) DataLoadArgs;
61 if (infoArgs == nullptr) {
62 LOG_ERROR(UDMF_KITS_NAPI, "No space for dataLoadArgs, udKey=%{public}s", udKey.c_str());
63 return false;
64 }
65 infoArgs->udKey = udKey;
66 infoArgs->dataLoadInfo = dataLoadInfo;
67 auto status = napi_call_threadsafe_function(tsfn, infoArgs, napi_tsfn_blocking);
68 if (status != napi_ok) {
69 LOG_ERROR(UDMF_KITS_NAPI, "call func failed,status=%{public}d,udKey=%{public}s", status, udKey.c_str());
70 }
71 napi_release_threadsafe_function(tsfn, napi_tsfn_release);
72 return false;
73 });
74 if (!tsfnExist) { LOG_ERROR(UDMF_KITS_NAPI, "Tsfn not exist, udKey=%{public}s", udKey.c_str()); }
75 };
76 return true;
77 }
78
CallDataLoadHandler(napi_env env,napi_value callback,void * context,void * data)79 void DataLoadParamsNapi::CallDataLoadHandler(napi_env env, napi_value callback, void *context, void *data)
80 {
81 DataLoadArgs* infoArgs = static_cast<DataLoadArgs*>(data);
82 std::string udKey = infoArgs->udKey;
83 napi_value param;
84 auto status = NapiDataUtils::SetValue(env, infoArgs->dataLoadInfo, param);
85 delete infoArgs;
86 if (status != napi_ok) {
87 LOG_ERROR(UDMF_KITS_NAPI, "SetValue dataLoadInfo failed, status=%{public}d", status);
88 return;
89 }
90 napi_value result = nullptr;
91 status = napi_call_function(env, nullptr, callback, 1, ¶m, &result);
92 if (status != napi_ok || result == nullptr) {
93 LOG_ERROR(UDMF_KITS_NAPI, "napi_call_function failed, status=%{public}d", status);
94 return;
95 }
96 LOG_INFO(UDMF_KITS_NAPI, "Call napi_call_function end.");
97 napi_valuetype type = napi_undefined;
98 napi_typeof(env, result, &type);
99 if (type == napi_null) {
100 LOG_ERROR(UDMF_KITS_NAPI, "DataLoad has no data");
101 return;
102 }
103 UnifiedDataNapi *unifiedDataNapi = nullptr;
104 status = napi_unwrap(env, result, reinterpret_cast<void **>(&unifiedDataNapi));
105 if (status != napi_ok || unifiedDataNapi == nullptr) {
106 LOG_ERROR(UDMF_KITS_NAPI, "napi_unwrap data failed, status=%{public}d", status);
107 return;
108 }
109
110 auto ret = UdmfClient::GetInstance().PushDelayData(udKey, *unifiedDataNapi->value_);
111 if (ret != E_OK) {
112 LOG_ERROR(UDMF_KITS_NAPI, "SetData failed, status=%{public}d", ret);
113 }
114 }
115 } // namespace UDMF
116 } // namespace OHOS