1 /*
2  * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <cstdio>
17 
18 #include "napi_utils.h"
19 #include "securec.h"
20 #include "avsession_log.h"
21 #include "av_session.h"
22 #include "napi_avcall_meta_data.h"
23 #include "napi_avcall_state.h"
24 #include "napi_meta_data.h"
25 #include "napi_playback_state.h"
26 #include "napi_media_description.h"
27 #include "napi_queue_item.h"
28 #include "native_engine/native_value.h"
29 #include "native_engine/native_engine.h"
30 #include "extension_context.h"
31 #include "ability_context.h"
32 #include "napi_common_want.h"
33 #include "napi_media_info_holder.h"
34 #include "pixel_map_napi.h"
35 #include "avsession_pixel_map_adapter.h"
36 #include "curl/curl.h"
37 #include "image_source.h"
38 #include "pixel_map.h"
39 
40 namespace OHOS::AVSession {
41 static constexpr int32_t STR_MAX_LENGTH = 40960;
42 static constexpr size_t STR_TAIL_LENGTH = 1;
43 
WriteCallback(std::uint8_t *ptr, size_t size, size_t nmemb, std::vector<std::uint8_t> *imgBuffer)44 size_t NapiUtils::WriteCallback(std::uint8_t *ptr, size_t size, size_t nmemb, std::vector<std::uint8_t> *imgBuffer)
45 {
46     size_t realsize = size * nmemb;
47     imgBuffer->reserve(realsize + imgBuffer->capacity());
48     for (size_t i = 0; i < realsize; i++) {
49         imgBuffer->push_back(ptr[i]);
50     }
51     return realsize;
52 }
53 
CurlSetRequestOptions(std::vector<std::uint8_t>& imgBuffer, const std::string uri)54 bool NapiUtils::CurlSetRequestOptions(std::vector<std::uint8_t>& imgBuffer, const std::string uri)
55 {
56     CURL *easyHandle_ = curl_easy_init();
57     if (easyHandle_) {
58         // set request options
59         curl_easy_setopt(easyHandle_, CURLOPT_URL, uri.c_str());
60         curl_easy_setopt(easyHandle_, CURLOPT_CONNECTTIMEOUT, NapiUtils::TIME_OUT_SECOND);
61         curl_easy_setopt(easyHandle_, CURLOPT_SSL_VERIFYPEER, 0L);
62         curl_easy_setopt(easyHandle_, CURLOPT_SSL_VERIFYHOST, 0L);
63         curl_easy_setopt(easyHandle_, CURLOPT_CAINFO, "/etc/ssl/certs/" "cacert.pem");
64         curl_easy_setopt(easyHandle_, CURLOPT_HTTPGET, 1L);
65         curl_easy_setopt(easyHandle_, CURLOPT_WRITEFUNCTION, WriteCallback);
66         curl_easy_setopt(easyHandle_, CURLOPT_WRITEDATA, &imgBuffer);
67 
68         // perform request
69         CURLcode res = curl_easy_perform(easyHandle_);
70         if (res != CURLE_OK) {
71             SLOGI("DoDownload curl easy_perform failure: %{public}s\n", curl_easy_strerror(res));
72             curl_easy_cleanup(easyHandle_);
73             easyHandle_ = nullptr;
74             return false;
75         } else {
76             int64_t httpCode = 0;
77             curl_easy_getinfo(easyHandle_, CURLINFO_RESPONSE_CODE, &httpCode);
78             SLOGI("DoDownload Http result " "%{public}" PRId64, httpCode);
79             CHECK_AND_RETURN_RET_LOG(httpCode < NapiUtils::HTTP_ERROR_CODE, false, "recv Http ERROR");
80             curl_easy_cleanup(easyHandle_);
81             easyHandle_ = nullptr;
82             return true;
83         }
84     }
85     return false;
86 }
87 
88 bool NapiUtils::DoDownloadInCommon(std::shared_ptr<Media::PixelMap>& pixelMap, const std::string uri)
89 {
90     SLOGI("DoDownloadInCommon with uri");
91 
92     std::vector<std::uint8_t> imgBuffer(0);
93     if (CurlSetRequestOptions(imgBuffer, uri) == true) {
94         std::uint8_t* buffer = (std::uint8_t*) calloc(imgBuffer.size(), sizeof(uint8_t));
95         if (buffer == nullptr) {
96             SLOGE("buffer malloc fail");
97             free(buffer);
98             return false;
99         }
100         std::copy(imgBuffer.begin(), imgBuffer.end(), buffer);
101         uint32_t errorCode = 0;
102         Media::SourceOptions opts;
103         SLOGD("DoDownload get size %{public}d", static_cast<int>(imgBuffer.size()));
104         auto imageSource = Media::ImageSource::CreateImageSource(buffer, imgBuffer.size(), opts, errorCode);
105         free(buffer);
106         if (errorCode || !imageSource) {
107             SLOGE("DoDownload create imageSource fail: %{public}u", errorCode);
108             return false;
109         }
110         Media::DecodeOptions decodeOpts;
111         pixelMap = imageSource->CreatePixelMap(decodeOpts, errorCode);
112         if (errorCode || pixelMap == nullptr) {
113             SLOGE("DoDownload creatPix fail: %{public}u, %{public}d", errorCode, static_cast<int>(pixelMap != nullptr));
114             return false;
115         }
116         return true;
117     }
118     return false;
119 }
120 
ConvertSessionType(const std::string& typeString)121 int32_t NapiUtils::ConvertSessionType(const std::string& typeString)
122 {
123     if (typeString == "audio") {
124         return AVSession::SESSION_TYPE_AUDIO;
125     } else if (typeString == "video") {
126         return AVSession::SESSION_TYPE_VIDEO;
127     } else if (typeString == "voice_call") {
128         return AVSession::SESSION_TYPE_VOICE_CALL;
129     } else if (typeString == "video_call") {
130         return AVSession::SESSION_TYPE_VIDEO_CALL;
131     } else {
132         return AVSession::SESSION_TYPE_INVALID;
133     }
134 }
135 
ConvertSessionType(int32_t type)136 std::string NapiUtils::ConvertSessionType(int32_t type)
137 {
138     if (type == AVSession::SESSION_TYPE_AUDIO) {
139         return "audio";
140     } else if (type == AVSession::SESSION_TYPE_VIDEO) {
141         return "video";
142     } else if (type == AVSession::SESSION_TYPE_VOICE_CALL) {
143         return "voice_call";
144     } else if (type == AVSession::SESSION_TYPE_VIDEO_CALL) {
145         return "video_call";
146     } else {
147         return "";
148     }
149 }
150 
151 /* napi_value <-> bool */
GetValue(napi_env env, napi_value in, bool& out)152 napi_status NapiUtils::GetValue(napi_env env, napi_value in, bool& out)
153 {
154     return napi_get_value_bool(env, in, &out);
155 }
156 
SetValue(napi_env env, const bool& in, napi_value& out)157 napi_status NapiUtils::SetValue(napi_env env, const bool& in, napi_value& out)
158 {
159     return napi_get_boolean(env, in, &out);
160 }
161 
162 /* napi_value <-> int32_t */
GetValue(napi_env env, napi_value in, int32_t& out)163 napi_status NapiUtils::GetValue(napi_env env, napi_value in, int32_t& out)
164 {
165     return napi_get_value_int32(env, in, &out);
166 }
167 
SetValue(napi_env env, const int32_t& in, napi_value& out)168 napi_status NapiUtils::SetValue(napi_env env, const int32_t& in, napi_value& out)
169 {
170     return napi_create_int32(env, in, &out);
171 }
172 
173 /* napi_value <-> uint32_t */
GetValue(napi_env env, napi_value in, uint32_t& out)174 napi_status NapiUtils::GetValue(napi_env env, napi_value in, uint32_t& out)
175 {
176     return napi_get_value_uint32(env, in, &out);
177 }
178 
SetValue(napi_env env, const uint32_t& in, napi_value& out)179 napi_status NapiUtils::SetValue(napi_env env, const uint32_t& in, napi_value& out)
180 {
181     return napi_create_uint32(env, in, &out);
182 }
183 
184 /* napi_value <-> int64_t */
GetValue(napi_env env, napi_value in, int64_t& out)185 napi_status NapiUtils::GetValue(napi_env env, napi_value in, int64_t& out)
186 {
187     return napi_get_value_int64(env, in, &out);
188 }
189 
SetValue(napi_env env, const int64_t& in, napi_value& out)190 napi_status NapiUtils::SetValue(napi_env env, const int64_t& in, napi_value& out)
191 {
192     return napi_create_int64(env, in, &out);
193 }
194 
195 /* napi_value <-> double */
GetValue(napi_env env, napi_value in, double& out)196 napi_status NapiUtils::GetValue(napi_env env, napi_value in, double& out)
197 {
198     return napi_get_value_double(env, in, &out);
199 }
200 
SetValue(napi_env env, const double& in, napi_value& out)201 napi_status NapiUtils::SetValue(napi_env env, const double& in, napi_value& out)
202 {
203     return napi_create_double(env, in, &out);
204 }
205 
206 /* napi_value <-> std::string */
GetValue(napi_env env, napi_value in, std::string& out)207 napi_status NapiUtils::GetValue(napi_env env, napi_value in, std::string& out)
208 {
209     napi_valuetype type = napi_undefined;
210     napi_status status = napi_typeof(env, in, &type);
211     CHECK_RETURN((status == napi_ok) && (type == napi_string), "invalid type", napi_invalid_arg);
212 
213     size_t maxLen = STR_MAX_LENGTH;
214     status = napi_get_value_string_utf8(env, in, nullptr, 0, &maxLen);
215     if (maxLen >= STR_MAX_LENGTH) {
216         return napi_invalid_arg;
217     }
218 
219     char buf[STR_MAX_LENGTH + STR_TAIL_LENGTH] {};
220     size_t len = 0;
221     status = napi_get_value_string_utf8(env, in, buf, maxLen + STR_TAIL_LENGTH, &len);
222     if (status == napi_ok) {
223         out = std::string(buf);
224     }
225     return status;
226 }
227 
SetValue(napi_env env, const std::string& in, napi_value& out)228 napi_status NapiUtils::SetValue(napi_env env, const std::string& in, napi_value& out)
229 {
230     return napi_create_string_utf8(env, in.c_str(), in.size(), &out);
231 }
232 
233 /* napi_value <-> AppExecFwk::ElementName */
SetValue(napi_env env, const AppExecFwk::ElementName& in, napi_value& out)234 napi_status NapiUtils::SetValue(napi_env env, const AppExecFwk::ElementName& in, napi_value& out)
235 {
236     napi_status status = napi_create_object(env, &out);
237     CHECK_RETURN((status == napi_ok) && (out != nullptr), "create object failed", status);
238 
239     napi_value property = nullptr;
240     status = SetValue(env, in.GetDeviceID(), property);
241     CHECK_RETURN((status == napi_ok) && (property != nullptr), "create property failed", status);
242     status = napi_set_named_property(env, out, "deviceId", property);
243     CHECK_RETURN(status == napi_ok, "napi_set_named_property failed", status);
244 
245     status = SetValue(env, in.GetBundleName(), property);
246     CHECK_RETURN((status == napi_ok) && (property != nullptr), "create property failed", status);
247     status = napi_set_named_property(env, out, "bundleName", property);
248     CHECK_RETURN(status == napi_ok, "napi_set_named_property failed", status);
249 
250     status = SetValue(env, in.GetAbilityName(), property);
251     CHECK_RETURN((status == napi_ok) && (property != nullptr), "create property failed", status);
252     status = napi_set_named_property(env, out, "abilityName", property);
253     CHECK_RETURN(status == napi_ok, "napi_set_named_property failed", status);
254 
255     return napi_ok;
256 }
257 
SetOutPutDeviceIdValue(napi_env env, const std::vector<std::string>& in, napi_value& out)258 napi_status NapiUtils::SetOutPutDeviceIdValue(napi_env env, const std::vector<std::string>& in, napi_value& out)
259 {
260     napi_status status = napi_create_array_with_length(env, in.size(), &out);
261     CHECK_RETURN(status == napi_ok, "create array failed!", status);
262     int index = 0;
263     for (auto& item : in) {
264         napi_value element = nullptr;
265         SetValue(env, static_cast<int32_t>(std::stoi(item)), element);
266         status = napi_set_element(env, out, index++, element);
267         CHECK_RETURN((status == napi_ok), "napi_set_element failed!", status);
268     }
269     return status;
270 }
271 
272 /* napi_value <-> AVSessionDescriptor */
SetValue(napi_env env, const AVSessionDescriptor& in, napi_value& out)273 napi_status NapiUtils::SetValue(napi_env env, const AVSessionDescriptor& in, napi_value& out)
274 {
275     napi_status status = napi_create_object(env, &out);
276     CHECK_RETURN((status == napi_ok) && (out != nullptr), "create object failed", status);
277 
278     napi_value property = nullptr;
279     status = SetValue(env, in.sessionId_, property);
280     CHECK_RETURN((status == napi_ok) && (property != nullptr), "create object failed", status);
281     status = napi_set_named_property(env, out, "sessionId", property);
282     CHECK_RETURN(status == napi_ok, "napi_set_named_property failed", status);
283 
284     status = SetValue(env, ConvertSessionType(in.sessionType_), property);
285     CHECK_RETURN((status == napi_ok) && (property != nullptr), "create object failed", status);
286     status = napi_set_named_property(env, out, "type", property);
287     CHECK_RETURN(status == napi_ok, "napi_set_named_property failed", status);
288 
289     status = SetValue(env, in.sessionTag_, property);
290     CHECK_RETURN((status == napi_ok) && (property != nullptr), "create object failed", status);
291     status = napi_set_named_property(env, out, "sessionTag", property);
292     CHECK_RETURN(status == napi_ok, "napi_set_named_property failed", status);
293 
294     status = SetValue(env, in.elementName_, property);
295     CHECK_RETURN((status == napi_ok) && (property != nullptr), "create object failed", status);
296     status = napi_set_named_property(env, out, "elementName", property);
297     CHECK_RETURN(status == napi_ok, "napi_set_named_property failed", status);
298 
299     status = SetValue(env, in.isActive_, property);
300     CHECK_RETURN((status == napi_ok) && (property != nullptr), "create object failed", status);
301     status = napi_set_named_property(env, out, "isActive", property);
302     CHECK_RETURN(status == napi_ok, "napi_set_named_property failed", status);
303 
304     status = SetValue(env, in.isTopSession_, property);
305     CHECK_RETURN((status == napi_ok) && (property != nullptr), "create object failed", status);
306     status = napi_set_named_property(env, out, "isTopSession", property);
307     CHECK_RETURN(status == napi_ok, "napi_set_named_property failed", status);
308 
309     status = SetValue(env, in.outputDeviceInfo_, property);
310     CHECK_RETURN((status == napi_ok) && (property != nullptr), "create object failed", status);
311     status = napi_set_named_property(env, out, "outputDevice", property);
312     CHECK_RETURN(status == napi_ok, "napi_set_named_property failed", status);
313 
314     return napi_ok;
315 }
316 
317 /* napi_value <-> AVQueueInfo */
SetValue(napi_env env, const AVQueueInfo& in, napi_value& out)318 napi_status NapiUtils::SetValue(napi_env env, const AVQueueInfo& in, napi_value& out)
319 {
320     napi_status status = napi_create_object(env, &out);
321     CHECK_RETURN((status == napi_ok) && (out != nullptr), "create object failed", status);
322 
323     napi_value property = nullptr;
324     status = SetValue(env, in.GetBundleName(), property);
325     CHECK_RETURN((status == napi_ok) && (property != nullptr), "create object failed", status);
326     status = napi_set_named_property(env, out, "bundleName", property);
327     CHECK_RETURN(status == napi_ok, "napi_set_named_property failed", status);
328 
329     status = SetValue(env, in.GetAVQueueName(), property);
330     CHECK_RETURN((status == napi_ok) && (property != nullptr), "create object failed", status);
331     status = napi_set_named_property(env, out, "avQueueName", property);
332     CHECK_RETURN(status == napi_ok, "napi_set_named_property failed", status);
333 
334     status = SetValue(env, in.GetAVQueueId(), property);
335     CHECK_RETURN((status == napi_ok) && (property != nullptr), "create object failed", status);
336     status = napi_set_named_property(env, out, "avQueueId", property);
337     CHECK_RETURN(status == napi_ok, "napi_set_named_property failed", status);
338 
339     auto pixelMap = in.GetAVQueueImage();
340     if (pixelMap != nullptr) {
341         SLOGD(" napi setvalue has avqueueimage");
342         property = Media::PixelMapNapi::CreatePixelMap(env, AVSessionPixelMapAdapter::ConvertFromInner(pixelMap));
343         status = napi_set_named_property(env, out, "avQueueImage", property);
344         CHECK_RETURN(status == napi_ok, "set property failed", status);
345     }
346 
347     auto uri = in.GetAVQueueImageUri();
348     if (!uri.empty()) {
349         SLOGD(" napi setvalue has avqueueimageuri");
350         status = NapiUtils::SetValue(env, uri, property);
351         CHECK_RETURN((status == napi_ok) && (property != nullptr), "create property failed", status);
352         status = napi_set_named_property(env, out, "avQueueImage", property);
353         CHECK_RETURN(status == napi_ok, "set property failed", status);
354     }
355 
356     return napi_ok;
357 }
358 
359 /* napi_value <-> MMI::KeyEvent::KeyItem */
GetValue(napi_env env, napi_value in, MMI::KeyEvent::KeyItem& out)360 napi_status NapiUtils::GetValue(napi_env env, napi_value in, MMI::KeyEvent::KeyItem& out)
361 {
362     int32_t code {};
363     auto status = GetNamedProperty(env, in, "code", code);
364     CHECK_RETURN(status == napi_ok, "get code property failed", status);
365     SLOGI("code=%{public}d", code);
366     out.SetKeyCode(code);
367 
368     int64_t pressedTime {};
369     status = GetNamedProperty(env, in, "pressedTime", pressedTime);
370     CHECK_RETURN(status == napi_ok, "get pressedTime property failed", status);
371     SLOGI("pressedTime=%{public}" PRIu64, pressedTime);
372     out.SetDownTime(pressedTime);
373 
374     int32_t deviceId {};
375     status = GetNamedProperty(env, in, "deviceId", deviceId);
376     CHECK_RETURN(status == napi_ok, "get deviceId property failed", status);
377     out.SetDeviceId(deviceId);
378     out.SetPressed(true);
379 
380     return status;
381 }
382 
SetValue(napi_env env, const std::optional<MMI::KeyEvent::KeyItem> in, napi_value& out)383 napi_status NapiUtils::SetValue(napi_env env, const std::optional<MMI::KeyEvent::KeyItem> in, napi_value& out)
384 {
385     auto status = napi_create_object(env, &out);
386     CHECK_RETURN(status == napi_ok, "create object failed", status);
387 
388     napi_value code {};
389     status = SetValue(env, in->GetKeyCode(), code);
390     CHECK_RETURN((status == napi_ok) && (code != nullptr), "create property failed", status);
391     status = napi_set_named_property(env, out, "code", code);
392     CHECK_RETURN(status == napi_ok, "set property failed", status);
393 
394     napi_value pressedTime {};
395     status = SetValue(env, in->GetDownTime(), pressedTime);
396     CHECK_RETURN((status == napi_ok) && (pressedTime != nullptr), "create property failed", status);
397     status = napi_set_named_property(env, out, "pressedTime", pressedTime);
398     CHECK_RETURN(status == napi_ok, "set property failed", status);
399 
400     napi_value deviceId {};
401     status = SetValue(env, in->GetDeviceId(), deviceId);
402     CHECK_RETURN((status == napi_ok) && (deviceId != nullptr), "create property failed", status);
403     status = napi_set_named_property(env, out, "deviceId", deviceId);
404     CHECK_RETURN(status == napi_ok, "set property failed", status);
405 
406     return status;
407 }
408 
409 /* napi_value <-> MMI::KeyEvent */
GetValue(napi_env env, napi_value in, std::shared_ptr<MMI::KeyEvent>& out)410 napi_status NapiUtils::GetValue(napi_env env, napi_value in, std::shared_ptr<MMI::KeyEvent>& out)
411 {
412     napi_valuetype valueType = napi_undefined;
413     auto status = napi_typeof(env, in, &valueType);
414     CHECK_RETURN((status == napi_ok) && (valueType == napi_object), "object type invalid", status);
415 
416     out = MMI::KeyEvent::Create();
417     CHECK_RETURN(out != nullptr, "create keyEvent failed", napi_generic_failure);
418 
419     int32_t action {};
420     status = GetNamedProperty(env, in, "action", action);
421     CHECK_RETURN(status == napi_ok, "get action property failed", napi_generic_failure);
422     SLOGI("action=%{public}d", action);
423     action += KEYEVENT_ACTION_JS_NATIVE_DELTA;
424     out->SetKeyAction(action);
425 
426     MMI::KeyEvent::KeyItem key;
427     status = GetNamedProperty(env, in, "key", key);
428     CHECK_RETURN(status == napi_ok, "get action property failed", napi_generic_failure);
429     out->SetKeyCode(key.GetKeyCode());
430 
431     napi_value keyItems {};
432     status = napi_get_named_property(env, in, "keys", &keyItems);
433     CHECK_RETURN((status == napi_ok) && (keyItems != nullptr), "get keys property failed", status);
434 
435     uint32_t length {};
436     status = napi_get_array_length(env, keyItems, &length);
437     CHECK_RETURN(status == napi_ok, "get array length failed", status);
438 
439     for (uint32_t i = 0; i < length; ++i) {
440         napi_value keyItem {};
441         status = napi_get_element(env, keyItems, i, &keyItem);
442         CHECK_RETURN((status == napi_ok) && (keyItem != nullptr), "get element failed", status);
443         MMI::KeyEvent::KeyItem item;
444         status = GetValue(env, keyItem, item);
445         CHECK_RETURN(status == napi_ok, "get KeyItem failed", status);
446         if ((key.GetKeyCode() == item.GetKeyCode()) && (action == MMI::KeyEvent::KEY_ACTION_UP)) {
447             item.SetPressed(false);
448         }
449         out->AddKeyItem(item);
450     }
451 
452     return napi_ok;
453 }
454 
SetValue(napi_env env, const std::shared_ptr<MMI::KeyEvent>& in, napi_value& out)455 napi_status NapiUtils::SetValue(napi_env env, const std::shared_ptr<MMI::KeyEvent>& in, napi_value& out)
456 {
457     CHECK_RETURN(in != nullptr, "key event is nullptr", napi_generic_failure);
458 
459     auto status = napi_create_object(env, &out);
460     CHECK_RETURN(status == napi_ok, "create object failed", status);
461 
462     napi_value action {};
463     status = SetValue(env, in->GetKeyAction() - KEYEVENT_ACTION_JS_NATIVE_DELTA, action);
464     CHECK_RETURN((status == napi_ok) && (action != nullptr), "create action property failed", status);
465     status = napi_set_named_property(env, out, "action", action);
466     CHECK_RETURN(status == napi_ok, "set action property failed", status);
467 
468     napi_value key {};
469     CHECK_RETURN(in->GetKeyItem(), "get key item failed", napi_generic_failure);
470     status = SetValue(env, in->GetKeyItem(), key);
471     CHECK_RETURN((status == napi_ok) && (key != nullptr), "create key property failed", status);
472     status = napi_set_named_property(env, out, "key", key);
473     CHECK_RETURN(status == napi_ok, "set key property failed", status);
474 
475     napi_value keys {};
476     status = napi_create_array(env, &keys);
477     CHECK_RETURN(status == napi_ok, "create array failed", status);
478 
479     uint32_t idx = 0;
480     std::vector<MMI::KeyEvent::KeyItem> keyItems = in->GetKeyItems();
481     for (const auto& keyItem : keyItems) {
482         napi_value item {};
483         status = SetValue(env, keyItem, item);
484         CHECK_RETURN((status == napi_ok) && (item != nullptr), "create keyItem failed", status);
485 
486         status = napi_set_element(env, keys, idx, item);
487         CHECK_RETURN(status == napi_ok, "set element failed", status);
488         ++idx;
489     }
490 
491     status = napi_set_named_property(env, out, "keys", keys);
492     CHECK_RETURN(status == napi_ok, "set keys property failed", status);
493     return status;
494 }
495 
496 /* napi_value <-> AbilityRuntime::WantAgent::WantAgent */
GetValue(napi_env env, napi_value in, AbilityRuntime::WantAgent::WantAgent*& out)497 napi_status NapiUtils::GetValue(napi_env env, napi_value in, AbilityRuntime::WantAgent::WantAgent*& out)
498 {
499     auto status = napi_unwrap(env, in, reinterpret_cast<void**>(&out));
500     CHECK_RETURN(status == napi_ok, "unwrap failed", napi_invalid_arg);
501     return status;
502 }
503 
SetValue(napi_env env, AbilityRuntime::WantAgent::WantAgent& in, napi_value& out)504 napi_status NapiUtils::SetValue(napi_env env, AbilityRuntime::WantAgent::WantAgent& in, napi_value& out)
505 {
506     auto status = napi_create_object(env, &out);
507     CHECK_RETURN(status == napi_ok, "create object failed", napi_generic_failure);
508     auto finalizecb = [](napi_env env, void* data, void* hint) {};
509     status = napi_wrap(env, out, static_cast<void*>(&in), finalizecb, nullptr, nullptr);
510     CHECK_RETURN(status == napi_ok, "wrap object failed", napi_generic_failure);
511     return status;
512 }
513 
514 /* napi_value <-> AAFwk::WantParams */
GetValue(napi_env env, napi_value in, AAFwk::WantParams& out)515 napi_status NapiUtils::GetValue(napi_env env, napi_value in, AAFwk::WantParams& out)
516 {
517     auto status = AppExecFwk::UnwrapWantParams(env, in, out);
518     CHECK_RETURN(status == true, "unwrap object failed", napi_generic_failure);
519     return napi_ok;
520 }
521 
SetValue(napi_env env, const AAFwk::WantParams& in, napi_value& out)522 napi_status NapiUtils::SetValue(napi_env env, const AAFwk::WantParams& in, napi_value& out)
523 {
524     auto status = napi_create_object(env, &out);
525     CHECK_RETURN(status == napi_ok, "create object failed", napi_generic_failure);
526     out = AppExecFwk::WrapWantParams(env, in);
527     return status;
528 }
529 
530 /* napi_value <-> AVCallMetaData */
GetValue(napi_env env, napi_value in, AVCallMetaData& out)531 napi_status NapiUtils::GetValue(napi_env env, napi_value in, AVCallMetaData& out)
532 {
533     return NapiAVCallMetaData::GetValue(env, in, out);
534 }
535 
SetValue(napi_env env, const AVCallMetaData& in, napi_value& out)536 napi_status NapiUtils::SetValue(napi_env env, const AVCallMetaData& in, napi_value& out)
537 {
538     return NapiAVCallMetaData::SetValue(env, in, out);
539 }
540 
541 /* napi_value <-> AVCallState */
GetValue(napi_env env, napi_value in, AVCallState& out)542 napi_status NapiUtils::GetValue(napi_env env, napi_value in, AVCallState& out)
543 {
544     return NapiAVCallState::GetValue(env, in, out);
545 }
546 
SetValue(napi_env env, const AVCallState& in, napi_value& out)547 napi_status NapiUtils::SetValue(napi_env env, const AVCallState& in, napi_value& out)
548 {
549     return NapiAVCallState::SetValue(env, in, out);
550 }
551 
552 /* napi_value <-> AVMetaData */
GetValue(napi_env env, napi_value in, AVMetaData& out)553 napi_status NapiUtils::GetValue(napi_env env, napi_value in, AVMetaData& out)
554 {
555     return NapiMetaData::GetValue(env, in, out);
556 }
557 
SetValue(napi_env env, const AVMetaData& in, napi_value& out)558 napi_status NapiUtils::SetValue(napi_env env, const AVMetaData& in, napi_value& out)
559 {
560     return NapiMetaData::SetValue(env, in, out);
561 }
562 
563 /* napi_value <-> AVMediaDescription */
GetValue(napi_env env, napi_value in, AVMediaDescription& out)564 napi_status NapiUtils::GetValue(napi_env env, napi_value in, AVMediaDescription& out)
565 {
566     return NapiMediaDescription::GetValue(env, in, out);
567 }
568 
SetValue(napi_env env, const AVMediaDescription& in, napi_value& out)569 napi_status NapiUtils::SetValue(napi_env env, const AVMediaDescription& in, napi_value& out)
570 {
571     return NapiMediaDescription::SetValue(env, in, out);
572 }
573 
574 /* napi_value <-> AVQueueItem */
GetValue(napi_env env, napi_value in, AVQueueItem& out)575 napi_status NapiUtils::GetValue(napi_env env, napi_value in, AVQueueItem& out)
576 {
577     return NapiQueueItem::GetValue(env, in, out);
578 }
579 
SetValue(napi_env env, const AVQueueItem& in, napi_value& out)580 napi_status NapiUtils::SetValue(napi_env env, const AVQueueItem& in, napi_value& out)
581 {
582     return NapiQueueItem::SetValue(env, in, out);
583 }
584 
585 /* napi_value <-> std::vector<AVQueueItem> */
GetValue(napi_env env, napi_value in, std::vector<AVQueueItem>& out)586 napi_status NapiUtils::GetValue(napi_env env, napi_value in, std::vector<AVQueueItem>& out)
587 {
588     uint32_t length {};
589     auto status = napi_get_array_length(env, in, &length);
590     CHECK_RETURN(status == napi_ok, "get AVQueueItem array length failed", status);
591     for (uint32_t i = 0; i < length; ++i) {
592         napi_value element {};
593         status = napi_get_element(env, in, i, &element);
594         CHECK_RETURN((status == napi_ok) && (element != nullptr), "get element failed", status);
595         AVQueueItem descriptor;
596         status = GetValue(env, element, descriptor);
597         out.push_back(descriptor);
598     }
599     return status;
600 }
601 
SetValue(napi_env env, const std::vector<AVQueueItem>& in, napi_value& out)602 napi_status NapiUtils::SetValue(napi_env env, const std::vector<AVQueueItem>& in, napi_value& out)
603 {
604     SLOGD("napi_value <- std::vector<std::string>");
605     napi_status status = napi_create_array_with_length(env, in.size(), &out);
606     CHECK_RETURN(status == napi_ok, "create AVQueueItem array failed!", status);
607     int index = 0;
608     for (auto& item : in) {
609         napi_value element = nullptr;
610         SetValue(env, item, element);
611         status = napi_set_element(env, out, index++, element);
612         CHECK_RETURN((status == napi_ok), "napi_set_element failed!", status);
613     }
614     return status;
615 }
616 
617 /* napi_value <-> AVPlaybackState */
GetValue(napi_env env, napi_value in, AVPlaybackState& out)618 napi_status NapiUtils::GetValue(napi_env env, napi_value in, AVPlaybackState& out)
619 {
620     return NapiPlaybackState::GetValue(env, in, out);
621 }
622 
SetValue(napi_env env, const AVPlaybackState& in, napi_value& out)623 napi_status NapiUtils::SetValue(napi_env env, const AVPlaybackState& in, napi_value& out)
624 {
625     return NapiPlaybackState::SetValue(env, in, out);
626 }
627 
628 /* napi_value <-> AVCastPlayerState */
GetValue(napi_env env, napi_value in, AVCastPlayerState& out)629 napi_status NapiUtils::GetValue(napi_env env, napi_value in, AVCastPlayerState& out)
630 {
631     napi_valuetype type = napi_undefined;
632     napi_status status = napi_typeof(env, in, &type);
633     CHECK_RETURN((status == napi_ok) && (type == napi_string), "invalid type", napi_invalid_arg);
634 
635     size_t maxLen = STR_MAX_LENGTH;
636     status = napi_get_value_string_utf8(env, in, nullptr, 0, &maxLen);
637     if (maxLen >= STR_MAX_LENGTH) {
638         return napi_invalid_arg;
639     }
640 
641     char buf[STR_MAX_LENGTH + STR_TAIL_LENGTH] {};
642     size_t len = 0;
643     status = napi_get_value_string_utf8(env, in, buf, maxLen + STR_TAIL_LENGTH, &len);
644     if (status == napi_ok) {
645         AVCastPlayerState castPlayerState;
646         castPlayerState.castPlayerState_ = std::string(buf);
647         out = castPlayerState;
648     }
649     return status;
650 }
651 
SetValue(napi_env env, const AVCastPlayerState& in, napi_value& out)652 napi_status NapiUtils::SetValue(napi_env env, const AVCastPlayerState& in, napi_value& out)
653 {
654     return napi_create_string_utf8(env, in.castPlayerState_.c_str(), in.castPlayerState_.size(), &out);
655 }
656 
657 /* napi_value <-> std::vector<std::string> */
GetValue(napi_env env, napi_value in, std::vector<std::string>& out)658 napi_status NapiUtils::GetValue(napi_env env, napi_value in, std::vector<std::string>& out)
659 {
660     SLOGD("napi_value -> std::vector<std::string>");
661     out.clear();
662     bool isArray = false;
663     napi_is_array(env, in, &isArray);
664     CHECK_RETURN(isArray, "not an array", napi_invalid_arg);
665 
666     uint32_t length = 0;
667     napi_status status = napi_get_array_length(env, in, &length);
668     CHECK_RETURN((status == napi_ok) && (length > 0 || length == 0), "get_array failed!", napi_invalid_arg);
669     for (uint32_t i = 0; i < length; ++i) {
670         napi_value item = nullptr;
671         status = napi_get_element(env, in, i, &item);
672         CHECK_RETURN((item != nullptr) && (status == napi_ok), "no element", napi_invalid_arg);
673         std::string value;
674         status = GetValue(env, item, value);
675         CHECK_RETURN(status == napi_ok, "not a string", napi_invalid_arg);
676         out.push_back(value);
677     }
678     return status;
679 }
680 
SetValue(napi_env env, const std::vector<std::string>& in, napi_value& out)681 napi_status NapiUtils::SetValue(napi_env env, const std::vector<std::string>& in, napi_value& out)
682 {
683     SLOGD("napi_value <- std::vector<std::string>");
684     napi_status status = napi_create_array_with_length(env, in.size(), &out);
685     CHECK_RETURN(status == napi_ok, "create array failed!", status);
686     int index = 0;
687     for (auto& item : in) {
688         napi_value element = nullptr;
689         SetValue(env, item, element);
690         status = napi_set_element(env, out, index++, element);
691         CHECK_RETURN((status == napi_ok), "napi_set_element failed!", status);
692     }
693     return status;
694 }
695 
696 /* napi_value <-> std::vector<uint8_t> */
GetValue(napi_env env, napi_value in, std::vector<uint8_t>& out)697 napi_status NapiUtils::GetValue(napi_env env, napi_value in, std::vector<uint8_t>& out)
698 {
699     out.clear();
700     SLOGD("napi_value -> std::vector<uint8_t> ");
701     napi_typedarray_type type = napi_biguint64_array;
702     size_t length = 0;
703     napi_value buffer = nullptr;
704     size_t offset = 0;
705     void* data = nullptr;
706     napi_status status = napi_get_typedarray_info(env, in, &type, &length, &data, &buffer, &offset);
707     SLOGD("array type=%{public}d length=%{public}d offset=%{public}d", static_cast<int>(type), static_cast<int>(length),
708           static_cast<int>(offset));
709     CHECK_RETURN(status == napi_ok, "napi_get_typedarray_info failed!", napi_invalid_arg);
710     CHECK_RETURN(type == napi_uint8_array, "is not Uint8Array!", napi_invalid_arg);
711     CHECK_RETURN((length > 0) && (data != nullptr), "invalid data!", napi_invalid_arg);
712     out.assign(static_cast<uint8_t*>(data), static_cast<uint8_t*>(data) + length);
713     return status;
714 }
715 
SetValue(napi_env env, const std::vector<uint8_t>& in, napi_value& out)716 napi_status NapiUtils::SetValue(napi_env env, const std::vector<uint8_t>& in, napi_value& out)
717 {
718     SLOGD("napi_value <- std::vector<uint8_t> ");
719     CHECK_RETURN(!in.empty(), "invalid std::vector<uint8_t>", napi_invalid_arg);
720     void* data = nullptr;
721     napi_value buffer = nullptr;
722     napi_status status = napi_create_arraybuffer(env, in.size(), &data, &buffer);
723     CHECK_RETURN((status == napi_ok), "create array buffer failed!", status);
724 
725     if (memcpy_s(data, in.size(), in.data(), in.size()) != EOK) {
726         SLOGE("memcpy_s not EOK");
727         return napi_invalid_arg;
728     }
729     status = napi_create_typedarray(env, napi_uint8_array, in.size(), buffer, 0, &out);
730     CHECK_RETURN((status == napi_ok), "napi_value <- std::vector<uint8_t> invalid value", status);
731     return status;
732 }
733 
734 /* napi_value <-> CastDisplayInfo */
SetValue(napi_env env, const CastDisplayInfo& in, napi_value& out)735 napi_status NapiUtils::SetValue(napi_env env, const CastDisplayInfo& in, napi_value& out)
736 {
737     auto status = napi_create_object(env, &out);
738     CHECK_RETURN(status == napi_ok, "create object failed", status);
739     napi_value displayState = nullptr;
740     napi_create_int32(env, static_cast<int>(in.displayState), &displayState);
741     status = napi_set_named_property(env, out, "state", displayState);
742     napi_value displayId = nullptr;
743     napi_create_int64(env, in.displayId, &displayId);
744     status = napi_set_named_property(env, out, "id", displayId);
745     napi_value name = nullptr;
746     napi_create_string_utf8(env, in.name.c_str(), in.name.size(), &name);
747     status = napi_set_named_property(env, out, "name", name);
748     napi_value width = nullptr;
749     napi_create_int32(env, in.width, &width);
750     status = napi_set_named_property(env, out, "width", width);
751     napi_value height = nullptr;
752     napi_create_int32(env, in.height, &height);
753     status = napi_set_named_property(env, out, "height", height);
754     CHECK_RETURN(status == napi_ok, "set property failed", status);
755     return status;
756 }
757 
758 /* napi_value <-> CastDisplayInfo Array */
SetValue(napi_env env, const std::vector<CastDisplayInfo>& in, napi_value& out)759 napi_status NapiUtils::SetValue(napi_env env, const std::vector<CastDisplayInfo>& in, napi_value& out)
760 {
761     auto status = napi_create_array_with_length(env, in.size(), &out);
762     CHECK_RETURN(status == napi_ok, "create CastDisplayInfo Array failed", status);
763     int index = 0;
764     for (auto& item : in) {
765         napi_value element = nullptr;
766         SetValue(env, item, element);
767         status = napi_set_element(env, out, index++, element);
768         CHECK_RETURN(status == napi_ok, "napi_set_element failed", status);
769     }
770     return status;
771 }
772 
773 template <typename T>
TypedArray2Vector(uint8_t* data, size_t length, napi_typedarray_type type, std::vector<T>& out)774 void TypedArray2Vector(uint8_t* data, size_t length, napi_typedarray_type type, std::vector<T>& out)
775 {
776     auto convert = [&out](auto* data, size_t elements) {
777         for (size_t index = 0; index < elements; index++) {
778             out.push_back(static_cast<T>(data[index]));
779         }
780     };
781 
782     switch (type) {
783         case napi_int8_array:
784             convert(reinterpret_cast<int8_t*>(data), length);
785             break;
786         case napi_uint8_array:
787             convert(data, length);
788             break;
789         case napi_uint8_clamped_array:
790             convert(data, length);
791             break;
792         case napi_int16_array:
793             convert(reinterpret_cast<int16_t*>(data), length / sizeof(int16_t));
794             break;
795         case napi_uint16_array:
796             convert(reinterpret_cast<uint16_t*>(data), length / sizeof(uint16_t));
797             break;
798         case napi_int32_array:
799             convert(reinterpret_cast<int32_t*>(data), length / sizeof(int32_t));
800             break;
801         case napi_uint32_array:
802             convert(reinterpret_cast<uint32_t*>(data), length / sizeof(uint32_t));
803             break;
804         case napi_float32_array:
805             convert(reinterpret_cast<float*>(data), length / sizeof(float));
806             break;
807         case napi_float64_array:
808             convert(reinterpret_cast<double*>(data), length / sizeof(double));
809             break;
810         case napi_bigint64_array:
811             convert(reinterpret_cast<int64_t*>(data), length / sizeof(int64_t));
812             break;
813         case napi_biguint64_array:
814             convert(reinterpret_cast<uint64_t*>(data), length / sizeof(uint64_t));
815             break;
816         default:
817             CHECK_RETURN_VOID(false, "[FATAL] invalid napi_typedarray_type!");
818     }
819 }
820 
821 /* napi_value <-> std::vector<int32_t> */
GetValue(napi_env env, napi_value in, std::vector<int32_t>& out)822 napi_status NapiUtils::GetValue(napi_env env, napi_value in, std::vector<int32_t>& out)
823 {
824     out.clear();
825     SLOGD("napi_value -> std::vector<int32_t> ");
826     napi_typedarray_type type = napi_biguint64_array;
827     size_t length = 0;
828     napi_value buffer = nullptr;
829     size_t offset = 0;
830     uint8_t* data = nullptr;
831     napi_status status = napi_get_typedarray_info(env, in, &type, &length,
832                                                   reinterpret_cast<void**>(&data), &buffer, &offset);
833     SLOGD("array type=%{public}d length=%{public}d offset=%{public}d", static_cast<int>(type), static_cast<int>(length),
834           static_cast<int>(offset));
835     CHECK_RETURN(status == napi_ok, "napi_get_typedarray_info failed!", napi_invalid_arg);
836     CHECK_RETURN(type <= napi_int32_array, "is not int32 supported typed array!", napi_invalid_arg);
837     CHECK_RETURN((length > 0) && (data != nullptr), "invalid data!", napi_invalid_arg);
838     TypedArray2Vector<int32_t>(data, length, type, out);
839     return status;
840 }
841 
SetValue(napi_env env, const std::vector<int32_t>& in, napi_value& out)842 napi_status NapiUtils::SetValue(napi_env env, const std::vector<int32_t>& in, napi_value& out)
843 {
844     SLOGD("napi_value <- std::vector<int32_t> ");
845     size_t bytes = in.size() * sizeof(int32_t);
846     CHECK_RETURN(bytes > 0, "invalid std::vector<int32_t>", napi_invalid_arg);
847     void* data = nullptr;
848     napi_value buffer = nullptr;
849     napi_status status = napi_create_arraybuffer(env, bytes, &data, &buffer);
850     CHECK_RETURN((status == napi_ok), "invalid buffer", status);
851 
852     if (memcpy_s(data, bytes, in.data(), bytes) != EOK) {
853         SLOGE("memcpy_s not EOK");
854         return napi_invalid_arg;
855     }
856     status = napi_create_typedarray(env, napi_int32_array, in.size(), buffer, 0, &out);
857     CHECK_RETURN((status == napi_ok), "invalid buffer", status);
858     return status;
859 }
860 
861 /* napi_value <-> std::vector<uint32_t> */
GetValue(napi_env env, napi_value in, std::vector<uint32_t>& out)862 napi_status NapiUtils::GetValue(napi_env env, napi_value in, std::vector<uint32_t>& out)
863 {
864     out.clear();
865     SLOGD("napi_value -> std::vector<uint32_t> ");
866     napi_typedarray_type type = napi_biguint64_array;
867     size_t length = 0;
868     napi_value buffer = nullptr;
869     size_t offset = 0;
870     uint8_t* data = nullptr;
871     napi_status status = napi_get_typedarray_info(env, in, &type, &length,
872                                                   reinterpret_cast<void**>(&data), &buffer, &offset);
873     SLOGD("napi_get_typedarray_info type=%{public}d", static_cast<int>(type));
874     CHECK_RETURN(status == napi_ok, "napi_get_typedarray_info failed!", napi_invalid_arg);
875     CHECK_RETURN((type <= napi_uint16_array) || (type == napi_uint32_array), "invalid type!", napi_invalid_arg);
876     CHECK_RETURN((length > 0) && (data != nullptr), "invalid data!", napi_invalid_arg);
877     TypedArray2Vector<uint32_t>(data, length, type, out);
878     return status;
879 }
880 
SetValue(napi_env env, const std::vector<uint32_t>& in, napi_value& out)881 napi_status NapiUtils::SetValue(napi_env env, const std::vector<uint32_t>& in, napi_value& out)
882 {
883     SLOGD("napi_value <- std::vector<uint32_t> ");
884     size_t bytes = in.size() * sizeof(uint32_t);
885     CHECK_RETURN(bytes > 0, "invalid std::vector<uint32_t>", napi_invalid_arg);
886     void* data = nullptr;
887     napi_value buffer = nullptr;
888     napi_status status = napi_create_arraybuffer(env, bytes, &data, &buffer);
889     CHECK_RETURN((status == napi_ok), "invalid buffer", status);
890 
891     if (memcpy_s(data, bytes, in.data(), bytes) != EOK) {
892         SLOGE("memcpy_s not EOK");
893         return napi_invalid_arg;
894     }
895     status = napi_create_typedarray(env, napi_uint32_array, in.size(), buffer, 0, &out);
896     CHECK_RETURN((status == napi_ok), "invalid buffer", status);
897     return status;
898 }
899 
900 /* napi_value <-> std::vector<int64_t> */
GetValue(napi_env env, napi_value in, std::vector<int64_t>& out)901 napi_status NapiUtils::GetValue(napi_env env, napi_value in, std::vector<int64_t>& out)
902 {
903     out.clear();
904     SLOGD("napi_value -> std::vector<int64_t> ");
905     napi_typedarray_type type = napi_biguint64_array;
906     size_t length = 0;
907     napi_value buffer = nullptr;
908     size_t offset = 0;
909     uint8_t* data = nullptr;
910     napi_status status = napi_get_typedarray_info(env, in, &type, &length,
911                                                   reinterpret_cast<void**>(&data), &buffer, &offset);
912     SLOGD("array type=%{public}d length=%{public}d offset=%{public}d", static_cast<int>(type), static_cast<int>(length),
913           static_cast<int>(offset));
914     CHECK_RETURN(status == napi_ok, "napi_get_typedarray_info failed!", napi_invalid_arg);
915     CHECK_RETURN((type <= napi_uint32_array) || (type == napi_bigint64_array), "invalid type!", napi_invalid_arg);
916     CHECK_RETURN((length > 0) && (data != nullptr), "invalid data!", napi_invalid_arg);
917     TypedArray2Vector<int64_t>(data, length, type, out);
918     return status;
919 }
920 
SetValue(napi_env env, const std::vector<int64_t>& in, napi_value& out)921 napi_status NapiUtils::SetValue(napi_env env, const std::vector<int64_t>& in, napi_value& out)
922 {
923     SLOGD("napi_value <- std::vector<int64_t> ");
924     size_t bytes = in.size() * sizeof(int64_t);
925     CHECK_RETURN(bytes > 0, "invalid std::vector<uint32_t>", napi_invalid_arg);
926     void* data = nullptr;
927     napi_value buffer = nullptr;
928     napi_status status = napi_create_arraybuffer(env, bytes, &data, &buffer);
929     CHECK_RETURN((status == napi_ok), "invalid buffer", status);
930 
931     if (memcpy_s(data, bytes, in.data(), bytes) != EOK) {
932         SLOGE("memcpy_s not EOK");
933         return napi_invalid_arg;
934     }
935     status = napi_create_typedarray(env, napi_bigint64_array, in.size(), buffer, 0, &out);
936     CHECK_RETURN((status == napi_ok), "invalid buffer", status);
937     return status;
938 }
939 /* napi_value <-> std::vector<double> */
GetValue(napi_env env, napi_value in, std::vector<double>& out)940 napi_status NapiUtils::GetValue(napi_env env, napi_value in, std::vector<double>& out)
941 {
942     out.clear();
943     bool isTypedArray = false;
944     napi_status status = napi_is_typedarray(env, in, &isTypedArray);
945     SLOGD("napi_value -> std::vector<double> input %{public}s a TypedArray", isTypedArray ? "is" : "is not");
946     CHECK_RETURN((status == napi_ok), "napi_is_typedarray failed!", status);
947     if (isTypedArray) {
948         SLOGD("napi_value -> std::vector<double> ");
949         napi_typedarray_type type = napi_biguint64_array;
950         size_t length = 0;
951         napi_value buffer = nullptr;
952         size_t offset = 0;
953         uint8_t* data = nullptr;
954         status = napi_get_typedarray_info(env, in, &type, &length, reinterpret_cast<void**>(&data), &buffer, &offset);
955         SLOGD("napi_get_typedarray_info status=%{public}d type=%{public}d", status, static_cast<int>(type));
956         CHECK_RETURN(status == napi_ok, "napi_get_typedarray_info failed!", napi_invalid_arg);
957         CHECK_RETURN((length > 0) && (data != nullptr), "invalid data!", napi_invalid_arg);
958         TypedArray2Vector<double>(data, length, type, out);
959     } else {
960         bool isArray = false;
961         status = napi_is_array(env, in, &isArray);
962         SLOGD("napi_value -> std::vector<double> input %{public}s an Array", isArray ? "is" : "is not");
963         CHECK_RETURN((status == napi_ok) && isArray, "invalid data!", napi_invalid_arg);
964         uint32_t length = 0;
965         status = napi_get_array_length(env, in, &length);
966         CHECK_RETURN((status == napi_ok) && (length > 0), "invalid data!", napi_invalid_arg);
967         for (uint32_t i = 0; i < length; ++i) {
968             napi_value item = nullptr;
969             status = napi_get_element(env, in, i, &item);
970             CHECK_RETURN((item != nullptr) && (status == napi_ok), "no element", napi_invalid_arg);
971             double vi = 0.0f;
972             status = napi_get_value_double(env, item, &vi);
973             CHECK_RETURN(status == napi_ok, "element not a double", napi_invalid_arg);
974             out.push_back(vi);
975         }
976     }
977     return status;
978 }
979 
SetValue(napi_env env, const std::vector<double>& in, napi_value& out)980 napi_status NapiUtils::SetValue(napi_env env, const std::vector<double>& in, napi_value& out)
981 {
982     SLOGD("napi_value <- std::vector<double> ");
983     (void)(env);
984     (void)(in);
985     (void)(out);
986     CHECK_RETURN(false, "std::vector<double> to napi_value, unsupported!", napi_invalid_arg);
987     return napi_invalid_arg;
988 }
989 
990 /* std::vector<AVSessionDescriptor> <-> napi_value */
SetValue(napi_env env, const std::vector<AVSessionDescriptor>& in, napi_value& out)991 napi_status NapiUtils::SetValue(napi_env env, const std::vector<AVSessionDescriptor>& in, napi_value& out)
992 {
993     SLOGD("napi_value <- std::vector<AVSessionDescriptor>  %{public}d", static_cast<int>(in.size()));
994     napi_status status = napi_create_array_with_length(env, in.size(), &out);
995     CHECK_RETURN((status == napi_ok), "create_array failed!", status);
996     int index = 0;
997     for (const auto& item : in) {
998         napi_value entry = nullptr;
999         SetValue(env, item, entry);
1000         napi_set_element(env, out, index++, entry);
1001     }
1002     return status;
1003 }
1004 
1005 /* std::vector<AVQueueInfo> <-> napi_value */
SetValue(napi_env env, const std::vector<AVQueueInfo>& in, napi_value& out)1006 napi_status NapiUtils::SetValue(napi_env env, const std::vector<AVQueueInfo>& in, napi_value& out)
1007 {
1008     SLOGD("napi_value <- std::vector<AVQueueInfo>  %{public}d", static_cast<int>(in.size()));
1009     napi_status status = napi_create_array_with_length(env, in.size(), &out);
1010     CHECK_RETURN((status == napi_ok), "create_array failed!", status);
1011     int index = 0;
1012     for (const auto& item : in) {
1013         napi_value entry = nullptr;
1014         SetValue(env, item, entry);
1015         napi_set_element(env, out, index++, entry);
1016     }
1017     return status;
1018 }
1019 
1020 /* napi_value <-> DeviceInfo */
SetValue(napi_env env, const DeviceInfo& in, napi_value& out)1021 napi_status NapiUtils::SetValue(napi_env env, const DeviceInfo& in, napi_value& out)
1022 {
1023     napi_status status = napi_create_object(env, &out);
1024     CHECK_RETURN((status == napi_ok) && (out != nullptr), "create object failed", status);
1025     napi_value property = nullptr;
1026     status = SetValue(env, in.castCategory_, property);
1027     CHECK_RETURN((status == napi_ok) && (property != nullptr), "create object failed", status);
1028     status = napi_set_named_property(env, out, "castCategory", property);
1029     CHECK_RETURN(status == napi_ok, "napi_set_named_property failed", status);
1030 
1031     status = SetValue(env, in.deviceId_, property);
1032     CHECK_RETURN((status == napi_ok) && (property != nullptr), "create object failed", status);
1033     status = napi_set_named_property(env, out, "deviceId", property);
1034     CHECK_RETURN(status == napi_ok, "napi_set_named_property failed", status);
1035 
1036     status = SetValue(env, in.manufacturer_, property);
1037     CHECK_RETURN((status == napi_ok) && (property != nullptr), "create object failed", status);
1038     status = napi_set_named_property(env, out, "manufacturer", property);
1039     CHECK_RETURN(status == napi_ok, "napi_set_named_property failed", status);
1040 
1041     status = SetValue(env, in.modelName_, property);
1042     CHECK_RETURN((status == napi_ok) && (property != nullptr), "create object failed", status);
1043     status = napi_set_named_property(env, out, "modelName", property);
1044     CHECK_RETURN(status == napi_ok, "napi_set_named_property failed", status);
1045 
1046     status = SetValue(env, in.deviceName_, property);
1047     CHECK_RETURN((status == napi_ok) && (property != nullptr), "create object failed", status);
1048     status = napi_set_named_property(env, out, "deviceName", property);
1049     CHECK_RETURN(status == napi_ok, "napi_set_named_property failed", status);
1050 
1051     status = SetValue(env, in.deviceType_, property);
1052     CHECK_RETURN((status == napi_ok) && (property != nullptr), "create object failed", status);
1053     status = napi_set_named_property(env, out, "deviceType", property);
1054     CHECK_RETURN(status == napi_ok, "napi_set_named_property failed", status);
1055 
1056     status = SetValue(env, in.ipAddress_, property);
1057     CHECK_RETURN((status == napi_ok) && (property != nullptr), "create object failed", status);
1058     status = napi_set_named_property(env, out, "ipAddress", property);
1059     CHECK_RETURN(status == napi_ok, "napi_set_named_property failed", status);
1060 
1061     status = SetValue(env, in.providerId_, property);
1062     CHECK_RETURN((status == napi_ok) && (property != nullptr), "create object failed", status);
1063     status = napi_set_named_property(env, out, "providerId", property);
1064     CHECK_RETURN(status == napi_ok, "napi_set_named_property failed", status);
1065 
1066     status = SetValue(env, in.supportedProtocols_, property);
1067     CHECK_RETURN((status == napi_ok) && (property != nullptr), "create object failed", status);
1068     status = napi_set_named_property(env, out, "supportedProtocols", property);
1069     CHECK_RETURN(status == napi_ok, "napi_set_named_property failed", status);
1070 
1071     status = SetValue(env, in.authenticationStatus_, property);
1072     CHECK_RETURN((status == napi_ok) && (property != nullptr), "create object failed", status);
1073     status = napi_set_named_property(env, out, "authenticationStatus", property);
1074     CHECK_RETURN(status == napi_ok, "napi_set_named_property failed", status);
1075 
1076     status = SetValue(env, in.supportedDrmCapabilities_, property);
1077     CHECK_RETURN((status == napi_ok) && (property != nullptr), "create object failed", status);
1078     status = napi_set_named_property(env, out, "supportedDrmCapabilities", property);
1079     CHECK_RETURN(status == napi_ok, "napi_set_named_property failed", status);
1080 
1081     status = SetValue(env, in.isLegacy_, property);
1082     CHECK_RETURN((status == napi_ok) && (property != nullptr), "create object failed", status);
1083     status = napi_set_named_property(env, out, "isLegacy", property);
1084     CHECK_RETURN(status == napi_ok, "napi_set_named_property failed", status);
1085 
1086     status = SetValue(env, in.mediumTypes_, property);
1087     CHECK_RETURN((status == napi_ok) && (property != nullptr), "create object failed", status);
1088     status = napi_set_named_property(env, out, "mediumTypes", property);
1089     CHECK_RETURN(status == napi_ok, "napi_set_named_property failed", status);
1090     return napi_ok;
1091 }
1092 
1093 /* OutputDeviceInfo <-> napi_value */
SetValue(napi_env env, const OutputDeviceInfo& in, napi_value& out)1094 napi_status NapiUtils::SetValue(napi_env env, const OutputDeviceInfo& in, napi_value& out)
1095 {
1096     SLOGD("napi_value <- OutputDeviceInfo");
1097     napi_value temp {};
1098     napi_create_object(env, &out);
1099 
1100     napi_status status = napi_create_array_with_length(env, in.deviceInfos_.size(), &temp);
1101     CHECK_RETURN((status == napi_ok), "create_array failed!", status);
1102     int index = 0;
1103     SLOGD("The length of deviceInfos is %{public}d", static_cast<int32_t>(in.deviceInfos_.size()));
1104     for (const auto& item : in.deviceInfos_) {
1105         napi_value entry = nullptr;
1106         status = SetValue(env, item, entry);
1107         CHECK_RETURN((status == napi_ok) && (entry != nullptr), "create array failed!", status);
1108         napi_set_element(env, temp, index++, entry);
1109     }
1110     status = napi_set_named_property(env, out, "devices", temp);
1111     CHECK_RETURN((status == napi_ok), "set named property devices failed", status);
1112     return status;
1113 }
1114 
Unwrap(napi_env env, napi_value in, void** out, napi_value constructor)1115 napi_status NapiUtils::Unwrap(napi_env env, napi_value in, void** out, napi_value constructor)
1116 {
1117     if (constructor != nullptr) {
1118         bool isInstance = false;
1119         napi_instanceof(env, in, constructor, &isInstance);
1120         if (!isInstance) {
1121             SLOGE("not a instance of *");
1122             return napi_invalid_arg;
1123         }
1124     }
1125     return napi_unwrap(env, in, out);
1126 }
1127 
Equals(napi_env env, napi_value value, napi_ref copy)1128 bool NapiUtils::Equals(napi_env env, napi_value value, napi_ref copy)
1129 {
1130     if (copy == nullptr) {
1131         return (value == nullptr);
1132     }
1133 
1134     napi_value copyValue = nullptr;
1135     napi_get_reference_value(env, copy, &copyValue);
1136     CHECK_RETURN((napi_get_reference_value(env, copy, &copyValue) == napi_ok),
1137                  "get ref value failed", napi_generic_failure);
1138     bool isEquals = false;
1139     CHECK_RETURN(napi_strict_equals(env, value, copyValue, &isEquals) == napi_ok,
1140                  "get equals result failed", napi_generic_failure);
1141     return isEquals;
1142 }
1143 
TypeCheck(napi_env env, napi_value value, napi_valuetype expectType)1144 bool NapiUtils::TypeCheck(napi_env env, napi_value value, napi_valuetype expectType)
1145 {
1146     napi_valuetype valueType = napi_undefined;
1147     napi_status status = napi_typeof(env, value, &valueType);
1148     if (status != napi_ok || valueType != expectType) {
1149         return false;
1150     }
1151     return true;
1152 }
1153 
GetUndefinedValue(napi_env env)1154 napi_value NapiUtils::GetUndefinedValue(napi_env env)
1155 {
1156     napi_value result {};
1157     napi_get_undefined(env, &result);
1158     return result;
1159 }
1160 
GetPropertyNames(napi_env env, napi_value in, std::vector<std::string>& out)1161 napi_status NapiUtils::GetPropertyNames(napi_env env, napi_value in, std::vector<std::string>& out)
1162 {
1163     napi_value names {};
1164     NAPI_CALL_BASE(env, napi_get_property_names(env, in, &names), napi_generic_failure);
1165     uint32_t length = 0;
1166     NAPI_CALL_BASE(env, napi_get_array_length(env, names, &length), napi_generic_failure);
1167 
1168     for (uint32_t index = 0; index < length; ++index) {
1169         napi_value name {};
1170         std::string nameString;
1171         if (napi_get_element(env, names, index, &name) != napi_ok) {
1172             continue;
1173         }
1174         if (GetValue(env, name, nameString) != napi_ok) {
1175             continue;
1176         }
1177         out.push_back(nameString);
1178     }
1179 
1180     return napi_ok;
1181 }
1182 
GetDateValue(napi_env env, napi_value value, double& result)1183 napi_status NapiUtils::GetDateValue(napi_env env, napi_value value, double& result)
1184 {
1185     CHECK_RETURN(env != nullptr, "env is nullptr", napi_invalid_arg);
1186     CHECK_RETURN(value != nullptr, "value is nullptr", napi_invalid_arg);
1187 
1188     SLOGD("GetDateValue in");
1189     bool isDate = false;
1190     napi_is_date(env, value, &isDate);
1191     if (isDate) {
1192         napi_status status = napi_get_date_value(env, value, &result);
1193         if (status != napi_ok) {
1194             SLOGE("get date error");
1195         }
1196         SLOGD("GetDateValue out");
1197         return napi_ok;
1198     } else {
1199         SLOGE("value is not date type");
1200         return napi_date_expected;
1201     }
1202 }
1203 
SetDateValue(napi_env env, double time, napi_value& result)1204 napi_status NapiUtils::SetDateValue(napi_env env, double time, napi_value& result)
1205 {
1206     CHECK_RETURN(env != nullptr, "env is nullptr", napi_invalid_arg);
1207 
1208     SLOGD("SetDateValue in");
1209     napi_status status = napi_create_date(env, time, &result);
1210     if (status != napi_ok) {
1211         SLOGE("create date error");
1212     }
1213     SLOGD("SetDateValue out");
1214     return napi_ok;
1215 }
1216 
GetRefByCallback(napi_env env, std::list<napi_ref> callbackList, napi_value callback, napi_ref& callbackRef)1217 napi_status NapiUtils::GetRefByCallback(napi_env env, std::list<napi_ref> callbackList, napi_value callback,
1218                                         napi_ref& callbackRef)
1219 {
1220     for (auto ref = callbackList.begin(); ref != callbackList.end(); ++ref) {
1221         if (Equals(env, callback, *ref)) {
1222             SLOGD("Callback has been matched");
1223             callbackRef = *ref;
1224             break;
1225         }
1226     }
1227     return napi_ok;
1228 }
1229 
1230 /* napi_value is napi stage context */
GetStageElementName(napi_env env, napi_value in, AppExecFwk::ElementName& out)1231 napi_status NapiUtils::GetStageElementName(napi_env env, napi_value in, AppExecFwk::ElementName& out)
1232 {
1233     std::shared_ptr<AbilityRuntime::Context> stageContext = AbilityRuntime::GetStageModeContext(env, in);
1234     CHECK_RETURN(stageContext != nullptr, "get StagContext failed", napi_generic_failure);
1235     std::shared_ptr <AppExecFwk::AbilityInfo> abilityInfo;
1236     auto abilityContext = AbilityRuntime::Context::ConvertTo<AbilityRuntime::AbilityContext>(stageContext);
1237     if (abilityContext != nullptr) {
1238         abilityInfo = abilityContext->GetAbilityInfo();
1239     } else {
1240         auto extensionContext = AbilityRuntime::Context::ConvertTo<AbilityRuntime::ExtensionContext>(stageContext);
1241         CHECK_RETURN(extensionContext != nullptr, "context ConvertTo AbilityContext and ExtensionContext fail",
1242                      napi_generic_failure);
1243         abilityInfo = extensionContext->GetAbilityInfo();
1244     }
1245     out.SetBundleName(abilityInfo->bundleName);
1246     out.SetAbilityName(abilityInfo->name);
1247     return napi_ok;
1248 }
1249 
GetFaElementName(napi_env env, AppExecFwk::ElementName& out)1250 napi_status NapiUtils::GetFaElementName(napi_env env, AppExecFwk::ElementName& out)
1251 {
1252     auto* ability = AbilityRuntime::GetCurrentAbility(env);
1253     CHECK_RETURN(ability != nullptr, "get feature ability failed", napi_generic_failure);
1254     auto want = ability->GetWant();
1255     CHECK_RETURN(want != nullptr, "get want failed", napi_generic_failure);
1256     out = want->GetElement();
1257     return napi_ok;
1258 }
1259 
GetValue(napi_env env, napi_value in, AppExecFwk::ElementName& out)1260 napi_status NapiUtils::GetValue(napi_env env, napi_value in, AppExecFwk::ElementName& out)
1261 {
1262     bool isStageMode = false;
1263     CHECK_RETURN(AbilityRuntime::IsStageContext(env, in, isStageMode) == napi_ok, "get context type failed",
1264                  napi_generic_failure);
1265     if (isStageMode) {
1266         CHECK_RETURN(GetStageElementName(env, in, out) == napi_ok, "get StagContext failed", napi_generic_failure);
1267     } else {
1268         CHECK_RETURN(GetFaElementName(env, out) == napi_ok, "get FaContext failed", napi_generic_failure);
1269     }
1270     return napi_ok;
1271 }
1272 
GetValue(napi_env env, napi_value in, SessionToken& out)1273 napi_status NapiUtils::GetValue(napi_env env, napi_value in, SessionToken& out)
1274 {
1275     napi_value value {};
1276     auto status = napi_get_named_property(env, in, "sessionId", &value);
1277     CHECK_RETURN(status == napi_ok, "get SessionToken sessionId failed", status);
1278     status = GetValue(env, value, out.sessionId);
1279     CHECK_RETURN(status == napi_ok, "get SessionToken sessionId value failed", status);
1280 
1281     bool hasPid = false;
1282     NAPI_CALL_BASE(env, napi_has_named_property(env, in, "pid", &hasPid), napi_invalid_arg);
1283     if (hasPid) {
1284         status = napi_get_named_property(env, in, "pid", &value);
1285         CHECK_RETURN(status == napi_ok, "get SessionToken pid failed", status);
1286         status = GetValue(env, value, out.pid);
1287         CHECK_RETURN(status == napi_ok, "get SessionToken pid value failed", status);
1288     } else {
1289         out.pid = 0;
1290     }
1291 
1292     bool hasUid = false;
1293     NAPI_CALL_BASE(env, napi_has_named_property(env, in, "uid", &hasUid), napi_invalid_arg);
1294     if (hasUid) {
1295         status = napi_get_named_property(env, in, "uid", &value);
1296         CHECK_RETURN(status == napi_ok, "get SessionToken uid failed", status);
1297         status = GetValue(env, value, out.pid);
1298         CHECK_RETURN(status == napi_ok, "get SessionToken uid value failed", status);
1299     } else {
1300         out.uid = 0;
1301     }
1302     return napi_ok;
1303 }
1304 
GetValue(napi_env env, napi_value in, AudioStandard::DeviceRole& out)1305 napi_status NapiUtils::GetValue(napi_env env, napi_value in, AudioStandard::DeviceRole& out)
1306 {
1307     int32_t deviceRole;
1308     auto status = GetValue(env, in, deviceRole);
1309     CHECK_RETURN(status == napi_ok, "get AudioDeviceDescriptor deviceRole failed", status);
1310     out = static_cast<AudioStandard::DeviceRole>(deviceRole);
1311     return napi_ok;
1312 }
1313 
GetValue(napi_env env, napi_value in, AudioStandard::DeviceType& out)1314 napi_status NapiUtils::GetValue(napi_env env, napi_value in, AudioStandard::DeviceType& out)
1315 {
1316     int32_t deviceType;
1317     auto status = GetValue(env, in, deviceType);
1318     CHECK_RETURN(status == napi_ok, "get AudioDeviceDescriptor deviceType failed", status);
1319     out = static_cast<AudioStandard::DeviceType>(deviceType);
1320     return napi_ok;
1321 }
1322 
GetSampleRate(napi_env env, napi_value in, AudioStandard::AudioSamplingRate& out)1323 napi_status NapiUtils::GetSampleRate(napi_env env, napi_value in, AudioStandard::AudioSamplingRate& out)
1324 {
1325     napi_value value {};
1326     auto status = napi_get_named_property(env, in, "sampleRates", &value);
1327     uint32_t length {};
1328     napi_get_array_length(env, value, &length);
1329     CHECK_RETURN(status == napi_ok, "get array length failed", status);
1330     if (length > 0) {
1331         napi_value element {};
1332         status = napi_get_element(env, value, 0, &element);
1333         CHECK_RETURN((status == napi_ok) && (element != nullptr), "get element failed", status);
1334         int32_t samplingRate;
1335         status = GetValue(env, element, samplingRate);
1336         CHECK_RETURN(status == napi_ok, "get AudioDeviceDescriptor audioStreamInfo_ samplingRate value failed", status);
1337         out = static_cast<AudioStandard::AudioSamplingRate>(samplingRate);
1338     }
1339     return status;
1340 }
1341 
GetChannels(napi_env env, napi_value in, AudioStandard::AudioChannel& out)1342 napi_status NapiUtils::GetChannels(napi_env env, napi_value in, AudioStandard::AudioChannel& out)
1343 {
1344     napi_value value {};
1345     auto status = napi_get_named_property(env, in, "channelCounts", &value);
1346     uint32_t length {};
1347     napi_get_array_length(env, value, &length);
1348     CHECK_RETURN(status == napi_ok, "get array length failed", status);
1349     if (length > 0) {
1350         napi_value element {};
1351         status = napi_get_element(env, value, 0, &element);
1352         CHECK_RETURN((status == napi_ok) && (element != nullptr), "get element failed", status);
1353         int32_t channel;
1354         status = GetValue(env, element, channel);
1355         CHECK_RETURN(status == napi_ok, "get AudioDeviceDescriptor audioStreamInfo_ channels value failed", status);
1356         out = static_cast<AudioStandard::AudioChannel>(channel);
1357     }
1358     return status;
1359 }
1360 
GetChannelMasks(napi_env env, napi_value in, int32_t& out)1361 napi_status NapiUtils::GetChannelMasks(napi_env env, napi_value in, int32_t& out)
1362 {
1363     napi_value value {};
1364     auto status = napi_get_named_property(env, in, "channelMasks", &value);
1365     uint32_t length {};
1366     napi_get_array_length(env, value, &length);
1367     CHECK_RETURN(status == napi_ok, "get array length failed", status);
1368     if (length > 0) {
1369         napi_value element {};
1370         status = napi_get_element(env, value, 0, &element);
1371         CHECK_RETURN((status == napi_ok) && (element != nullptr), "get element failed", status);
1372         status = GetValue(env, element, out);
1373         CHECK_RETURN(status == napi_ok, "get AudioDeviceDescriptor channelMasks_ value failed", status);
1374     }
1375     return status;
1376 }
1377 
GetValue(napi_env env, napi_value in, AudioStandard::AudioDeviceDescriptor& out)1378 napi_status NapiUtils::GetValue(napi_env env, napi_value in, AudioStandard::AudioDeviceDescriptor& out)
1379 {
1380     napi_value value {};
1381     auto status = napi_get_named_property(env, in, "id", &value);
1382     CHECK_RETURN(status == napi_ok, "get AudioDeviceDescriptor deviceId_ failed", status);
1383     status = GetValue(env, value, out.deviceId_);
1384     CHECK_RETURN(status == napi_ok, "get AudioDeviceDescriptor deviceId_ value failed", status);
1385 
1386     status = napi_get_named_property(env, in, "name", &value);
1387     CHECK_RETURN(status == napi_ok, "get AudioDeviceDescriptor deviceName_ failed", status);
1388     status = GetValue(env, value, out.deviceName_);
1389     CHECK_RETURN(status == napi_ok, "get AudioDeviceDescriptor deviceName_ value failed", status);
1390 
1391     status = napi_get_named_property(env, in, "networkId", &value);
1392     CHECK_RETURN(status == napi_ok, "get AudioDeviceDescriptor networkId failed", status);
1393     status = GetValue(env, value, out.networkId_);
1394     CHECK_RETURN(status == napi_ok, "get AudioDeviceDescriptor networkId value failed", status);
1395 
1396     status = napi_get_named_property(env, in, "deviceRole", &value);
1397     CHECK_RETURN(status == napi_ok, "get AudioDeviceDescriptor deviceRole_ failed", status);
1398     status = GetValue(env, value, out.deviceRole_);
1399     CHECK_RETURN(status == napi_ok, "get AudioDeviceDescriptor deviceRole_ value failed", status);
1400 
1401     if (napi_get_named_property(env, in, "address", &value) == napi_ok) {
1402         GetValue(env, value, out.macAddress_);
1403     }
1404 
1405     if (napi_get_named_property(env, in, "deviceType", &value) == napi_ok) {
1406         GetValue(env, value, out.deviceType_);
1407     }
1408 
1409     if (napi_get_named_property(env, in, "interruptGroupId", &value) == napi_ok) {
1410         GetValue(env, value, out.interruptGroupId_);
1411     }
1412 
1413     if (napi_get_named_property(env, in, "volumeGroupId", &value) == napi_ok) {
1414         GetValue(env, value, out.volumeGroupId_);
1415     }
1416 
1417     AudioStandard::AudioSamplingRate audioSamplingRate;
1418     GetSampleRate(env, in, audioSamplingRate);
1419     out.audioStreamInfo_.samplingRate = {audioSamplingRate};
1420 
1421     AudioStandard::AudioChannel audioChannel;
1422     GetChannels(env, in, audioChannel);
1423     out.audioStreamInfo_.channels = {audioChannel};
1424 
1425     GetChannelMasks(env, in, out.channelMasks_);
1426     return napi_ok;
1427 }
1428 
GetValue(napi_env env, napi_value in, std::vector<AudioStandard::AudioDeviceDescriptor>& out)1429 napi_status NapiUtils::GetValue(napi_env env, napi_value in, std::vector<AudioStandard::AudioDeviceDescriptor>& out)
1430 {
1431     uint32_t length {};
1432     auto status = napi_get_array_length(env, in, &length);
1433     CHECK_RETURN(status == napi_ok, "get array length failed", status);
1434     for (uint32_t i = 0; i < length; ++i) {
1435         napi_value element {};
1436         status = napi_get_element(env, in, i, &element);
1437         CHECK_RETURN((status == napi_ok) && (element != nullptr), "get element failed", status);
1438         AudioStandard::AudioDeviceDescriptor descriptor;
1439         status = GetValue(env, element, descriptor);
1440         out.push_back(descriptor);
1441     }
1442     return napi_ok;
1443 }
1444 
GetOptionalString(napi_env env, napi_value in, DeviceInfo& out)1445 napi_status NapiUtils::GetOptionalString(napi_env env, napi_value in, DeviceInfo& out)
1446 {
1447     napi_value value {};
1448     bool hasIpAddress = false;
1449     napi_has_named_property(env, in, "ipAddress", &hasIpAddress);
1450     if (hasIpAddress) {
1451         napi_status status = napi_get_named_property(env, in, "ipAddress", &value);
1452         CHECK_RETURN(status == napi_ok, "get DeviceInfo ipAddress failed", status);
1453 
1454         napi_valuetype type = napi_undefined;
1455         status = napi_typeof(env, value, &type);
1456         CHECK_RETURN((status == napi_ok) && type == napi_string, "invalid typ for ipAddress", napi_invalid_arg);
1457 
1458         size_t maxLen = STR_MAX_LENGTH;
1459         status = napi_get_value_string_utf8(env, value, nullptr, 0, &maxLen);
1460         if (maxLen == 0) {
1461             out.ipAddress_ = "";
1462         } else {
1463             if (maxLen < 0 || maxLen >= STR_MAX_LENGTH) {
1464                 return napi_invalid_arg;
1465             }
1466             char buf[STR_MAX_LENGTH + STR_TAIL_LENGTH] {};
1467             size_t len = 0;
1468             status = napi_get_value_string_utf8(env, value, buf, maxLen + STR_TAIL_LENGTH, &len);
1469             if (status == napi_ok) {
1470                 out.ipAddress_ = std::string(buf);
1471             }
1472         }
1473         CHECK_RETURN(status == napi_ok, "get DeviceInfo ipAddress value failed", status);
1474     } else {
1475         out.ipAddress_ = "";
1476     }
1477     return napi_ok;
1478 }
1479 
1480 /* napi_value -> DeviceInfo */
GetValue(napi_env env, napi_value in, DeviceInfo& out)1481 napi_status NapiUtils::GetValue(napi_env env, napi_value in, DeviceInfo& out)
1482 {
1483     napi_value value {};
1484     auto status = napi_get_named_property(env, in, "castCategory", &value);
1485     CHECK_RETURN(status == napi_ok, "get DeviceInfo castCategory_ failed", status);
1486     status = GetValue(env, value, out.castCategory_);
1487     CHECK_RETURN(status == napi_ok, "get DeviceInfo castCategory_ value failed", status);
1488     status = napi_get_named_property(env, in, "deviceId", &value);
1489     CHECK_RETURN(status == napi_ok, "get DeviceInfo deviceId_ failed", status);
1490     status = GetValue(env, value, out.deviceId_);
1491     CHECK_RETURN(status == napi_ok, "get DeviceInfo deviceId_ value failed", status);
1492     status = napi_get_named_property(env, in, "manufacturer", &value);
1493     CHECK_RETURN(status == napi_ok, "get DeviceInfo manufacturer_ failed", status);
1494     status = GetValue(env, value, out.manufacturer_);
1495     CHECK_RETURN(status == napi_ok, "get DeviceInfo manufacturer_ value failed", status);
1496     status = napi_get_named_property(env, in, "modelName", &value);
1497     CHECK_RETURN(status == napi_ok, "get DeviceInfo modelName_ failed", status);
1498     status = GetValue(env, value, out.modelName_);
1499     CHECK_RETURN(status == napi_ok, "get DeviceInfo modelName_ value failed", status);
1500     status = napi_get_named_property(env, in, "deviceName", &value);
1501     CHECK_RETURN(status == napi_ok, "get DeviceInfo deviceName_ failed", status);
1502     status = GetValue(env, value, out.deviceName_);
1503     CHECK_RETURN(status == napi_ok, "get DeviceInfo deviceName_ value failed", status);
1504     status = napi_get_named_property(env, in, "deviceType", &value);
1505     CHECK_RETURN(status == napi_ok, "get DeviceInfo deviceType_ failed", status);
1506     status = GetValue(env, value, out.deviceType_);
1507     CHECK_RETURN(status == napi_ok, "get DeviceInfo deviceType_ value failed", status);
1508     CHECK_RETURN(GetOptionalString(env, in, out) == napi_ok, "get DeviceInfo ip address value failed", status);
1509 
1510     bool hasKey = false;
1511     napi_has_named_property(env, in, "providerId", &hasKey);
1512     if (hasKey) {
1513         status = napi_get_named_property(env, in, "providerId", &value);
1514         CHECK_RETURN(status == napi_ok, "get DeviceInfo providerId failed", status);
1515         status = GetValue(env, value, out.providerId_);
1516         CHECK_RETURN(status == napi_ok, "get DeviceInfo providerId value failed", status);
1517     } else {
1518         out.providerId_ = 0;
1519     }
1520 
1521     status = ProcessDeviceInfoParams(env, in, out);
1522     CHECK_RETURN(status == napi_ok, "get DeviceInfo ProcessDeviceInfoParams failed", status);
1523 
1524     return napi_ok;
1525 }
1526 
ProcessDeviceInfoParams(napi_env env, napi_value in, DeviceInfo& out)1527 napi_status NapiUtils::ProcessDeviceInfoParams(napi_env env, napi_value in, DeviceInfo& out)
1528 {
1529     napi_value value {};
1530     bool hasKey = false;
1531     napi_status status = napi_ok;
1532     napi_has_named_property(env, in, "supportedProtocols", &hasKey);
1533     if (hasKey) {
1534         status = napi_get_named_property(env, in, "supportedProtocols", &value);
1535         CHECK_RETURN(status == napi_ok, "get DeviceInfo supportedProtocols failed", status);
1536         status = GetValue(env, value, out.supportedProtocols_);
1537         CHECK_RETURN(status == napi_ok, "get DeviceInfo supportedProtocols value failed", status);
1538     } else {
1539         out.supportedProtocols_ = ProtocolType::TYPE_CAST_PLUS_STREAM;
1540     }
1541     napi_has_named_property(env, in, "authenticationStatus", &hasKey);
1542     if (hasKey) {
1543         status = napi_get_named_property(env, in, "authenticationStatus", &value);
1544         CHECK_RETURN(status == napi_ok, "get DeviceInfo authenticationStatus failed", status);
1545         status = GetValue(env, value, out.authenticationStatus_);
1546         CHECK_RETURN(status == napi_ok, "get DeviceInfo authenticationStatus value failed", status);
1547     } else {
1548         out.authenticationStatus_ = 0;
1549     }
1550     napi_has_named_property(env, in, "supportedDrmCapabilities", &hasKey);
1551     if (hasKey) {
1552         status = napi_get_named_property(env, in, "supportedDrmCapabilities", &value);
1553         CHECK_RETURN(status == napi_ok, "get DeviceInfo supportedDrmCapabilities failed", status);
1554         status = GetValue(env, value, out.supportedDrmCapabilities_);
1555         CHECK_RETURN(status == napi_ok, "get DeviceInfo supportedDrmCapabilities value failed", status);
1556     }
1557     napi_has_named_property(env, in, "isLegacy", &hasKey);
1558     if (hasKey) {
1559         status = napi_get_named_property(env, in, "isLegacy", &value);
1560         CHECK_RETURN(status == napi_ok, "get DeviceInfo isLegacy failed", status);
1561         status = GetValue(env, value, out.isLegacy_);
1562         CHECK_RETURN(status == napi_ok, "get DeviceInfo isLegacy value failed", status);
1563     } else {
1564         out.isLegacy_ = false;
1565     }
1566     napi_has_named_property(env, in, "mediumTypes", &hasKey);
1567     if (hasKey) {
1568         status = napi_get_named_property(env, in, "mediumTypes", &value);
1569         CHECK_RETURN(status == napi_ok, "get DeviceInfo mediumTypes failed", status);
1570         status = GetValue(env, value, out.mediumTypes_);
1571         CHECK_RETURN(status == napi_ok, "get DeviceInfo mediumTypes value failed", status);
1572     } else {
1573         out.mediumTypes_ = COAP;
1574     }
1575     return napi_ok;
1576 }
1577 
1578 /* napi_value -> OutputDeviceInfo */
GetValue(napi_env env, napi_value in, OutputDeviceInfo& out)1579 napi_status NapiUtils::GetValue(napi_env env, napi_value in, OutputDeviceInfo& out)
1580 {
1581     napi_value devices = nullptr;
1582     bool hasProperty = false;
1583     NAPI_CALL_BASE(env, napi_has_named_property(env, in, "devices", &hasProperty), napi_invalid_arg);
1584     if (!hasProperty) {
1585         SLOGE("devices is not exit in OutputDeviceInfo");
1586         return napi_invalid_arg;
1587     }
1588     NAPI_CALL_BASE(env, napi_get_named_property(env, in, "devices", &devices), napi_invalid_arg);
1589     bool isArray = false;
1590     NAPI_CALL_BASE(env, napi_is_array(env, devices, &isArray), napi_invalid_arg);
1591     if (!isArray) {
1592         SLOGE("devices is not array");
1593         return napi_invalid_arg;
1594     }
1595 
1596     uint32_t arrLen = 0;
1597     NAPI_CALL_BASE(env, napi_get_array_length(env, devices, &arrLen), napi_invalid_arg);
1598     if (arrLen == 0) {
1599         SLOGE("devices len is invalid");
1600         return napi_invalid_arg;
1601     }
1602 
1603     for (uint32_t i = 0; i < arrLen; i++) {
1604         napi_value item = nullptr;
1605         NAPI_CALL_BASE(env, napi_get_element(env, devices, i, &item), napi_invalid_arg);
1606         DeviceInfo deviceInfo;
1607         napi_status status = GetValue(env, item, deviceInfo);
1608         CHECK_RETURN(status == napi_ok, "not is device info", status);
1609         out.deviceInfos_.push_back(deviceInfo);
1610     }
1611     return napi_ok;
1612 }
1613 
1614 /* napi_value -> MediaInfoHolder */
GetValue(napi_env env, napi_value in, MediaInfoHolder& out)1615 napi_status NapiUtils::GetValue(napi_env env, napi_value in, MediaInfoHolder& out)
1616 {
1617     return NapiMediaInfoHolder::GetValue(env, in, out);
1618 }
1619 
1620 /* napi_value <-> MediaInfoHolder */
SetValue(napi_env env, const MediaInfoHolder& in, napi_value& out)1621 napi_status NapiUtils::SetValue(napi_env env, const MediaInfoHolder& in, napi_value& out)
1622 {
1623     return NapiMediaInfoHolder::SetValue(env, in, out);
1624 }
1625 
1626 /* napi_value -> MediaInfo */
GetValue(napi_env env, napi_value in, MediaInfo& out)1627 napi_status NapiUtils::GetValue(napi_env env, napi_value in, MediaInfo& out)
1628 {
1629     napi_value value {};
1630     auto status = napi_get_named_property(env, in, "mediaId", &value);
1631     CHECK_RETURN(status == napi_ok, "get mediaId failed", status);
1632     status = GetValue(env, value, out.mediaId_);
1633     CHECK_RETURN(status == napi_ok, "get mediaId value failed", status);
1634 
1635     status = napi_get_named_property(env, in, "mediaUrl", &value);
1636     CHECK_RETURN(status == napi_ok, "get mediaUrl failed", status);
1637     status = GetValue(env, value, out.mediaUrl_);
1638     CHECK_RETURN(status == napi_ok, "get mediaUrl value failed", status);
1639 
1640     bool hasStartPosition = false;
1641     napi_has_named_property(env, in, "startPosition", &hasStartPosition);
1642     if (hasStartPosition) {
1643         status = napi_get_named_property(env, in, "startPosition", &value);
1644         CHECK_RETURN(status == napi_ok, "get MediaInfo startPosition failed", status);
1645         status = GetValue(env, value, out.startPosition_);
1646         CHECK_RETURN(status == napi_ok, "get MediaInfo startPosition value failed", status);
1647     } else {
1648         out.startPosition_ = -1;
1649     }
1650     return napi_ok;
1651 }
1652 
1653 /* napi_value <- MediaInfo */
SetValue(napi_env env, const MediaInfo& in, napi_value& out)1654 napi_status NapiUtils::SetValue(napi_env env, const MediaInfo& in, napi_value& out)
1655 {
1656     napi_status status = napi_create_object(env, &out);
1657     CHECK_RETURN((status == napi_ok) && (out != nullptr), "create object failed", status);
1658 
1659     napi_value property = nullptr;
1660     status = SetValue(env, in.mediaId_, property);
1661     CHECK_RETURN((status == napi_ok) && (property != nullptr), "create object failed", status);
1662     status = napi_set_named_property(env, out, "mediaId", property);
1663     CHECK_RETURN(status == napi_ok, "napi_set_named_property failed", status);
1664 
1665     status = SetValue(env, in.mediaUrl_, property);
1666     CHECK_RETURN((status == napi_ok) && (property != nullptr), "create object failed", status);
1667     status = napi_set_named_property(env, out, "mediaUrl", property);
1668     CHECK_RETURN(status == napi_ok, "napi_set_named_property failed", status);
1669 
1670     if (in.startPosition_ != -1) {
1671         status = SetValue(env, in.startPosition_, property);
1672         CHECK_RETURN((status == napi_ok) && (property != nullptr), "create object failed", status);
1673         status = napi_set_named_property(env, out, "mediaInfo", property);
1674         CHECK_RETURN(status == napi_ok, "napi_set_named_property failed", status);
1675     }
1676 
1677     return napi_ok;
1678 }
1679 
1680 /* napi_value -> AVFileDescriptor */
GetValue(napi_env env, napi_value in, AVFileDescriptor& out)1681 napi_status NapiUtils::GetValue(napi_env env, napi_value in, AVFileDescriptor& out)
1682 {
1683     napi_value value {};
1684     auto status = napi_ok;
1685     bool hasFd = false;
1686     napi_has_named_property(env, in, "fd", &hasFd);
1687     if (hasFd) {
1688         status = napi_get_named_property(env, in, "fd", &value);
1689         CHECK_RETURN(status == napi_ok, "get fd failed", status);
1690         status = GetValue(env, value, out.fd_);
1691         CHECK_RETURN(status == napi_ok, "get fd value failed", status);
1692     } else {
1693         out.fd_ = 0;
1694     }
1695 
1696     bool hasOffset = false;
1697     napi_has_named_property(env, in, "offset", &hasOffset);
1698     if (hasOffset) {
1699         status = napi_get_named_property(env, in, "offset", &value);
1700         CHECK_RETURN(status == napi_ok, "get offset failed", status);
1701         status = GetValue(env, value, out.offset_);
1702         CHECK_RETURN(status == napi_ok, "get offset value failed", status);
1703     } else {
1704         out.offset_ = 0;
1705     }
1706 
1707     bool hasLength = false;
1708     napi_has_named_property(env, in, "length", &hasLength);
1709     if (hasLength) {
1710         status = napi_get_named_property(env, in, "length", &value);
1711         CHECK_RETURN(status == napi_ok, "get length failed", status);
1712         status = GetValue(env, value, out.length_);
1713         CHECK_RETURN(status == napi_ok, "get length value failed", status);
1714     } else {
1715         out.length_ = -1;
1716     }
1717     return napi_ok;
1718 }
1719 
1720 /* napi_value <- AVFileDescriptor */
SetValue(napi_env env, const AVFileDescriptor& in, napi_value& out)1721 napi_status NapiUtils::SetValue(napi_env env, const AVFileDescriptor& in, napi_value& out)
1722 {
1723     napi_status status = napi_create_object(env, &out);
1724     CHECK_RETURN((status == napi_ok) && (out != nullptr), "create object failed", status);
1725 
1726     napi_value property = nullptr;
1727     status = SetValue(env, in.fd_, property);
1728     CHECK_RETURN((status == napi_ok) && (property != nullptr), "create object failed", status);
1729     status = napi_set_named_property(env, out, "fd", property);
1730     CHECK_RETURN(status == napi_ok, "napi_set_named_property failed", status);
1731 
1732     if (in.offset_ != 0) {
1733         status = SetValue(env, in.offset_, property);
1734         CHECK_RETURN((status == napi_ok) && (property != nullptr), "create object failed", status);
1735         status = napi_set_named_property(env, out, "offset", property);
1736         CHECK_RETURN(status == napi_ok, "napi_set_named_property failed", status);
1737     }
1738 
1739     if (in.length_ != -1) {
1740         status = SetValue(env, in.length_, property);
1741         CHECK_RETURN((status == napi_ok) && (property != nullptr), "create object failed", status);
1742         status = napi_set_named_property(env, out, "length", property);
1743         CHECK_RETURN(status == napi_ok, "napi_set_named_property failed", status);
1744     }
1745     return napi_ok;
1746 }
1747 
ThrowError(napi_env env, const char* napiMessage, int32_t napiCode)1748 napi_status NapiUtils::ThrowError(napi_env env, const char* napiMessage, int32_t napiCode)
1749 {
1750     napi_value message = nullptr;
1751     napi_value code = nullptr;
1752     napi_value result = nullptr;
1753     napi_create_string_utf8(env, napiMessage, NAPI_AUTO_LENGTH, &message);
1754     napi_create_error(env, nullptr, message, &result);
1755     napi_create_int32(env, napiCode, &code);
1756     napi_set_named_property(env, result, "code", code);
1757     napi_throw(env, result);
1758     return napi_ok;
1759 }
1760 }
1761