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 
DoDownloadInCommon(std::shared_ptr<Media::PixelMap> & pixelMap,const std::string uri)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 /* napi_value <-> NapiAVCastPickerOptions */
GetValue(napi_env env,napi_value in,NapiAVCastPickerOptions & out)774 napi_status NapiUtils::GetValue(napi_env env, napi_value in, NapiAVCastPickerOptions& out)
775 {
776     napi_value value {};
777     auto status = napi_get_named_property(env, in, "sessionType", &value);
778     CHECK_RETURN(status == napi_ok, "get sessionType failed", status);
779     status = GetValue(env, value, out.sessionType);
780     CHECK_RETURN(status == napi_ok, "get sessionType value failed", status);
781 
782     return napi_ok;
783 }
784 
785 template <typename T>
TypedArray2Vector(uint8_t * data,size_t length,napi_typedarray_type type,std::vector<T> & out)786 void TypedArray2Vector(uint8_t* data, size_t length, napi_typedarray_type type, std::vector<T>& out)
787 {
788     auto convert = [&out](auto* data, size_t elements) {
789         for (size_t index = 0; index < elements; index++) {
790             out.push_back(static_cast<T>(data[index]));
791         }
792     };
793 
794     switch (type) {
795         case napi_int8_array:
796             convert(reinterpret_cast<int8_t*>(data), length);
797             break;
798         case napi_uint8_array:
799             convert(data, length);
800             break;
801         case napi_uint8_clamped_array:
802             convert(data, length);
803             break;
804         case napi_int16_array:
805             convert(reinterpret_cast<int16_t*>(data), length / sizeof(int16_t));
806             break;
807         case napi_uint16_array:
808             convert(reinterpret_cast<uint16_t*>(data), length / sizeof(uint16_t));
809             break;
810         case napi_int32_array:
811             convert(reinterpret_cast<int32_t*>(data), length / sizeof(int32_t));
812             break;
813         case napi_uint32_array:
814             convert(reinterpret_cast<uint32_t*>(data), length / sizeof(uint32_t));
815             break;
816         case napi_float32_array:
817             convert(reinterpret_cast<float*>(data), length / sizeof(float));
818             break;
819         case napi_float64_array:
820             convert(reinterpret_cast<double*>(data), length / sizeof(double));
821             break;
822         case napi_bigint64_array:
823             convert(reinterpret_cast<int64_t*>(data), length / sizeof(int64_t));
824             break;
825         case napi_biguint64_array:
826             convert(reinterpret_cast<uint64_t*>(data), length / sizeof(uint64_t));
827             break;
828         default:
829             CHECK_RETURN_VOID(false, "[FATAL] invalid napi_typedarray_type!");
830     }
831 }
832 
833 /* napi_value <-> std::vector<int32_t> */
GetValue(napi_env env,napi_value in,std::vector<int32_t> & out)834 napi_status NapiUtils::GetValue(napi_env env, napi_value in, std::vector<int32_t>& out)
835 {
836     out.clear();
837     SLOGD("napi_value -> std::vector<int32_t> ");
838     napi_typedarray_type type = napi_biguint64_array;
839     size_t length = 0;
840     napi_value buffer = nullptr;
841     size_t offset = 0;
842     uint8_t* data = nullptr;
843     napi_status status = napi_get_typedarray_info(env, in, &type, &length,
844                                                   reinterpret_cast<void**>(&data), &buffer, &offset);
845     SLOGD("array type=%{public}d length=%{public}d offset=%{public}d", static_cast<int>(type), static_cast<int>(length),
846           static_cast<int>(offset));
847     CHECK_RETURN(status == napi_ok, "napi_get_typedarray_info failed!", napi_invalid_arg);
848     CHECK_RETURN(type <= napi_int32_array, "is not int32 supported typed array!", napi_invalid_arg);
849     CHECK_RETURN((length > 0) && (data != nullptr), "invalid data!", napi_invalid_arg);
850     TypedArray2Vector<int32_t>(data, length, type, out);
851     return status;
852 }
853 
SetValue(napi_env env,const std::vector<int32_t> & in,napi_value & out)854 napi_status NapiUtils::SetValue(napi_env env, const std::vector<int32_t>& in, napi_value& out)
855 {
856     SLOGD("napi_value <- std::vector<int32_t> ");
857     size_t bytes = in.size() * sizeof(int32_t);
858     CHECK_RETURN(bytes > 0, "invalid std::vector<int32_t>", napi_invalid_arg);
859     void* data = nullptr;
860     napi_value buffer = nullptr;
861     napi_status status = napi_create_arraybuffer(env, bytes, &data, &buffer);
862     CHECK_RETURN((status == napi_ok), "invalid buffer", status);
863 
864     if (memcpy_s(data, bytes, in.data(), bytes) != EOK) {
865         SLOGE("memcpy_s not EOK");
866         return napi_invalid_arg;
867     }
868     status = napi_create_typedarray(env, napi_int32_array, in.size(), buffer, 0, &out);
869     CHECK_RETURN((status == napi_ok), "invalid buffer", status);
870     return status;
871 }
872 
873 /* napi_value <-> std::vector<uint32_t> */
GetValue(napi_env env,napi_value in,std::vector<uint32_t> & out)874 napi_status NapiUtils::GetValue(napi_env env, napi_value in, std::vector<uint32_t>& out)
875 {
876     out.clear();
877     SLOGD("napi_value -> std::vector<uint32_t> ");
878     napi_typedarray_type type = napi_biguint64_array;
879     size_t length = 0;
880     napi_value buffer = nullptr;
881     size_t offset = 0;
882     uint8_t* data = nullptr;
883     napi_status status = napi_get_typedarray_info(env, in, &type, &length,
884                                                   reinterpret_cast<void**>(&data), &buffer, &offset);
885     SLOGD("napi_get_typedarray_info type=%{public}d", static_cast<int>(type));
886     CHECK_RETURN(status == napi_ok, "napi_get_typedarray_info failed!", napi_invalid_arg);
887     CHECK_RETURN((type <= napi_uint16_array) || (type == napi_uint32_array), "invalid type!", napi_invalid_arg);
888     CHECK_RETURN((length > 0) && (data != nullptr), "invalid data!", napi_invalid_arg);
889     TypedArray2Vector<uint32_t>(data, length, type, out);
890     return status;
891 }
892 
SetValue(napi_env env,const std::vector<uint32_t> & in,napi_value & out)893 napi_status NapiUtils::SetValue(napi_env env, const std::vector<uint32_t>& in, napi_value& out)
894 {
895     SLOGD("napi_value <- std::vector<uint32_t> ");
896     size_t bytes = in.size() * sizeof(uint32_t);
897     CHECK_RETURN(bytes > 0, "invalid std::vector<uint32_t>", napi_invalid_arg);
898     void* data = nullptr;
899     napi_value buffer = nullptr;
900     napi_status status = napi_create_arraybuffer(env, bytes, &data, &buffer);
901     CHECK_RETURN((status == napi_ok), "invalid buffer", status);
902 
903     if (memcpy_s(data, bytes, in.data(), bytes) != EOK) {
904         SLOGE("memcpy_s not EOK");
905         return napi_invalid_arg;
906     }
907     status = napi_create_typedarray(env, napi_uint32_array, in.size(), buffer, 0, &out);
908     CHECK_RETURN((status == napi_ok), "invalid buffer", status);
909     return status;
910 }
911 
912 /* napi_value <-> std::vector<int64_t> */
GetValue(napi_env env,napi_value in,std::vector<int64_t> & out)913 napi_status NapiUtils::GetValue(napi_env env, napi_value in, std::vector<int64_t>& out)
914 {
915     out.clear();
916     SLOGD("napi_value -> std::vector<int64_t> ");
917     napi_typedarray_type type = napi_biguint64_array;
918     size_t length = 0;
919     napi_value buffer = nullptr;
920     size_t offset = 0;
921     uint8_t* data = nullptr;
922     napi_status status = napi_get_typedarray_info(env, in, &type, &length,
923                                                   reinterpret_cast<void**>(&data), &buffer, &offset);
924     SLOGD("array type=%{public}d length=%{public}d offset=%{public}d", static_cast<int>(type), static_cast<int>(length),
925           static_cast<int>(offset));
926     CHECK_RETURN(status == napi_ok, "napi_get_typedarray_info failed!", napi_invalid_arg);
927     CHECK_RETURN((type <= napi_uint32_array) || (type == napi_bigint64_array), "invalid type!", napi_invalid_arg);
928     CHECK_RETURN((length > 0) && (data != nullptr), "invalid data!", napi_invalid_arg);
929     TypedArray2Vector<int64_t>(data, length, type, out);
930     return status;
931 }
932 
SetValue(napi_env env,const std::vector<int64_t> & in,napi_value & out)933 napi_status NapiUtils::SetValue(napi_env env, const std::vector<int64_t>& in, napi_value& out)
934 {
935     SLOGD("napi_value <- std::vector<int64_t> ");
936     size_t bytes = in.size() * sizeof(int64_t);
937     CHECK_RETURN(bytes > 0, "invalid std::vector<uint32_t>", napi_invalid_arg);
938     void* data = nullptr;
939     napi_value buffer = nullptr;
940     napi_status status = napi_create_arraybuffer(env, bytes, &data, &buffer);
941     CHECK_RETURN((status == napi_ok), "invalid buffer", status);
942 
943     if (memcpy_s(data, bytes, in.data(), bytes) != EOK) {
944         SLOGE("memcpy_s not EOK");
945         return napi_invalid_arg;
946     }
947     status = napi_create_typedarray(env, napi_bigint64_array, in.size(), buffer, 0, &out);
948     CHECK_RETURN((status == napi_ok), "invalid buffer", status);
949     return status;
950 }
951 /* napi_value <-> std::vector<double> */
GetValue(napi_env env,napi_value in,std::vector<double> & out)952 napi_status NapiUtils::GetValue(napi_env env, napi_value in, std::vector<double>& out)
953 {
954     out.clear();
955     bool isTypedArray = false;
956     napi_status status = napi_is_typedarray(env, in, &isTypedArray);
957     SLOGD("napi_value -> std::vector<double> input %{public}s a TypedArray", isTypedArray ? "is" : "is not");
958     CHECK_RETURN((status == napi_ok), "napi_is_typedarray failed!", status);
959     if (isTypedArray) {
960         SLOGD("napi_value -> std::vector<double> ");
961         napi_typedarray_type type = napi_biguint64_array;
962         size_t length = 0;
963         napi_value buffer = nullptr;
964         size_t offset = 0;
965         uint8_t* data = nullptr;
966         status = napi_get_typedarray_info(env, in, &type, &length, reinterpret_cast<void**>(&data), &buffer, &offset);
967         SLOGD("napi_get_typedarray_info status=%{public}d type=%{public}d", status, static_cast<int>(type));
968         CHECK_RETURN(status == napi_ok, "napi_get_typedarray_info failed!", napi_invalid_arg);
969         CHECK_RETURN((length > 0) && (data != nullptr), "invalid data!", napi_invalid_arg);
970         TypedArray2Vector<double>(data, length, type, out);
971     } else {
972         bool isArray = false;
973         status = napi_is_array(env, in, &isArray);
974         SLOGD("napi_value -> std::vector<double> input %{public}s an Array", isArray ? "is" : "is not");
975         CHECK_RETURN((status == napi_ok) && isArray, "invalid data!", napi_invalid_arg);
976         uint32_t length = 0;
977         status = napi_get_array_length(env, in, &length);
978         CHECK_RETURN((status == napi_ok) && (length > 0), "invalid data!", napi_invalid_arg);
979         for (uint32_t i = 0; i < length; ++i) {
980             napi_value item = nullptr;
981             status = napi_get_element(env, in, i, &item);
982             CHECK_RETURN((item != nullptr) && (status == napi_ok), "no element", napi_invalid_arg);
983             double vi = 0.0f;
984             status = napi_get_value_double(env, item, &vi);
985             CHECK_RETURN(status == napi_ok, "element not a double", napi_invalid_arg);
986             out.push_back(vi);
987         }
988     }
989     return status;
990 }
991 
SetValue(napi_env env,const std::vector<double> & in,napi_value & out)992 napi_status NapiUtils::SetValue(napi_env env, const std::vector<double>& in, napi_value& out)
993 {
994     SLOGD("napi_value <- std::vector<double> ");
995     (void)(env);
996     (void)(in);
997     (void)(out);
998     CHECK_RETURN(false, "std::vector<double> to napi_value, unsupported!", napi_invalid_arg);
999     return napi_invalid_arg;
1000 }
1001 
1002 /* std::vector<AVSessionDescriptor> <-> napi_value */
SetValue(napi_env env,const std::vector<AVSessionDescriptor> & in,napi_value & out)1003 napi_status NapiUtils::SetValue(napi_env env, const std::vector<AVSessionDescriptor>& in, napi_value& out)
1004 {
1005     SLOGD("napi_value <- std::vector<AVSessionDescriptor>  %{public}d", static_cast<int>(in.size()));
1006     napi_status status = napi_create_array_with_length(env, in.size(), &out);
1007     CHECK_RETURN((status == napi_ok), "create_array failed!", status);
1008     int index = 0;
1009     for (const auto& item : in) {
1010         napi_value entry = nullptr;
1011         SetValue(env, item, entry);
1012         napi_set_element(env, out, index++, entry);
1013     }
1014     return status;
1015 }
1016 
1017 /* std::vector<AVQueueInfo> <-> napi_value */
SetValue(napi_env env,const std::vector<AVQueueInfo> & in,napi_value & out)1018 napi_status NapiUtils::SetValue(napi_env env, const std::vector<AVQueueInfo>& in, napi_value& out)
1019 {
1020     SLOGD("napi_value <- std::vector<AVQueueInfo>  %{public}d", static_cast<int>(in.size()));
1021     napi_status status = napi_create_array_with_length(env, in.size(), &out);
1022     CHECK_RETURN((status == napi_ok), "create_array failed!", status);
1023     int index = 0;
1024     for (const auto& item : in) {
1025         napi_value entry = nullptr;
1026         SetValue(env, item, entry);
1027         napi_set_element(env, out, index++, entry);
1028     }
1029     return status;
1030 }
1031 
1032 /* napi_value <-> DeviceInfo */
SetValue(napi_env env,const DeviceInfo & in,napi_value & out)1033 napi_status NapiUtils::SetValue(napi_env env, const DeviceInfo& in, napi_value& out)
1034 {
1035     napi_status status = napi_create_object(env, &out);
1036     CHECK_RETURN((status == napi_ok) && (out != nullptr), "create object failed", status);
1037     napi_value property = nullptr;
1038     status = SetValue(env, in.castCategory_, property);
1039     CHECK_RETURN((status == napi_ok) && (property != nullptr), "create object failed", status);
1040     status = napi_set_named_property(env, out, "castCategory", property);
1041     CHECK_RETURN(status == napi_ok, "napi_set_named_property failed", status);
1042 
1043     status = SetValue(env, in.deviceId_, property);
1044     CHECK_RETURN((status == napi_ok) && (property != nullptr), "create object failed", status);
1045     status = napi_set_named_property(env, out, "deviceId", property);
1046     CHECK_RETURN(status == napi_ok, "napi_set_named_property failed", status);
1047 
1048     status = SetValue(env, in.manufacturer_, property);
1049     CHECK_RETURN((status == napi_ok) && (property != nullptr), "create object failed", status);
1050     status = napi_set_named_property(env, out, "manufacturer", property);
1051     CHECK_RETURN(status == napi_ok, "napi_set_named_property failed", status);
1052 
1053     status = SetValue(env, in.modelName_, property);
1054     CHECK_RETURN((status == napi_ok) && (property != nullptr), "create object failed", status);
1055     status = napi_set_named_property(env, out, "modelName", property);
1056     CHECK_RETURN(status == napi_ok, "napi_set_named_property failed", status);
1057 
1058     status = SetValue(env, in.deviceName_, property);
1059     CHECK_RETURN((status == napi_ok) && (property != nullptr), "create object failed", status);
1060     status = napi_set_named_property(env, out, "deviceName", property);
1061     CHECK_RETURN(status == napi_ok, "napi_set_named_property failed", status);
1062 
1063     status = SetValue(env, in.deviceType_, property);
1064     CHECK_RETURN((status == napi_ok) && (property != nullptr), "create object failed", status);
1065     status = napi_set_named_property(env, out, "deviceType", property);
1066     CHECK_RETURN(status == napi_ok, "napi_set_named_property failed", status);
1067 
1068     status = SetValue(env, in.ipAddress_, property);
1069     CHECK_RETURN((status == napi_ok) && (property != nullptr), "create object failed", status);
1070     status = napi_set_named_property(env, out, "ipAddress", property);
1071     CHECK_RETURN(status == napi_ok, "napi_set_named_property failed", status);
1072 
1073     status = SetValue(env, in.providerId_, property);
1074     CHECK_RETURN((status == napi_ok) && (property != nullptr), "create object failed", status);
1075     status = napi_set_named_property(env, out, "providerId", property);
1076     CHECK_RETURN(status == napi_ok, "napi_set_named_property failed", status);
1077 
1078     status = SetValue(env, in.supportedProtocols_, property);
1079     CHECK_RETURN((status == napi_ok) && (property != nullptr), "create object failed", status);
1080     status = napi_set_named_property(env, out, "supportedProtocols", property);
1081     CHECK_RETURN(status == napi_ok, "napi_set_named_property failed", status);
1082 
1083     status = SetValue(env, in.authenticationStatus_, property);
1084     CHECK_RETURN((status == napi_ok) && (property != nullptr), "create object failed", status);
1085     status = napi_set_named_property(env, out, "authenticationStatus", property);
1086     CHECK_RETURN(status == napi_ok, "napi_set_named_property failed", status);
1087 
1088     status = SetValue(env, in.supportedDrmCapabilities_, property);
1089     CHECK_RETURN((status == napi_ok) && (property != nullptr), "create object failed", status);
1090     status = napi_set_named_property(env, out, "supportedDrmCapabilities", property);
1091     CHECK_RETURN(status == napi_ok, "napi_set_named_property failed", status);
1092 
1093     status = SetValue(env, in.isLegacy_, property);
1094     CHECK_RETURN((status == napi_ok) && (property != nullptr), "create object failed", status);
1095     status = napi_set_named_property(env, out, "isLegacy", property);
1096     CHECK_RETURN(status == napi_ok, "napi_set_named_property failed", status);
1097 
1098     status = SetValue(env, in.mediumTypes_, property);
1099     CHECK_RETURN((status == napi_ok) && (property != nullptr), "create object failed", status);
1100     status = napi_set_named_property(env, out, "mediumTypes", property);
1101     CHECK_RETURN(status == napi_ok, "napi_set_named_property failed", status);
1102     return napi_ok;
1103 }
1104 
1105 /* OutputDeviceInfo <-> napi_value */
SetValue(napi_env env,const OutputDeviceInfo & in,napi_value & out)1106 napi_status NapiUtils::SetValue(napi_env env, const OutputDeviceInfo& in, napi_value& out)
1107 {
1108     SLOGD("napi_value <- OutputDeviceInfo");
1109     napi_value temp {};
1110     napi_create_object(env, &out);
1111 
1112     napi_status status = napi_create_array_with_length(env, in.deviceInfos_.size(), &temp);
1113     CHECK_RETURN((status == napi_ok), "create_array failed!", status);
1114     int index = 0;
1115     SLOGD("The length of deviceInfos is %{public}d", static_cast<int32_t>(in.deviceInfos_.size()));
1116     for (const auto& item : in.deviceInfos_) {
1117         napi_value entry = nullptr;
1118         status = SetValue(env, item, entry);
1119         CHECK_RETURN((status == napi_ok) && (entry != nullptr), "create array failed!", status);
1120         napi_set_element(env, temp, index++, entry);
1121     }
1122     status = napi_set_named_property(env, out, "devices", temp);
1123     CHECK_RETURN((status == napi_ok), "set named property devices failed", status);
1124     return status;
1125 }
1126 
Unwrap(napi_env env,napi_value in,void ** out,napi_value constructor)1127 napi_status NapiUtils::Unwrap(napi_env env, napi_value in, void** out, napi_value constructor)
1128 {
1129     if (constructor != nullptr) {
1130         bool isInstance = false;
1131         napi_instanceof(env, in, constructor, &isInstance);
1132         if (!isInstance) {
1133             SLOGE("not a instance of *");
1134             return napi_invalid_arg;
1135         }
1136     }
1137     return napi_unwrap(env, in, out);
1138 }
1139 
Equals(napi_env env,napi_value value,napi_ref copy)1140 bool NapiUtils::Equals(napi_env env, napi_value value, napi_ref copy)
1141 {
1142     if (copy == nullptr) {
1143         return (value == nullptr);
1144     }
1145 
1146     napi_value copyValue = nullptr;
1147     napi_get_reference_value(env, copy, &copyValue);
1148     CHECK_RETURN((napi_get_reference_value(env, copy, &copyValue) == napi_ok),
1149                  "get ref value failed", napi_generic_failure);
1150     bool isEquals = false;
1151     CHECK_RETURN(napi_strict_equals(env, value, copyValue, &isEquals) == napi_ok,
1152                  "get equals result failed", napi_generic_failure);
1153     return isEquals;
1154 }
1155 
TypeCheck(napi_env env,napi_value value,napi_valuetype expectType)1156 bool NapiUtils::TypeCheck(napi_env env, napi_value value, napi_valuetype expectType)
1157 {
1158     napi_valuetype valueType = napi_undefined;
1159     napi_status status = napi_typeof(env, value, &valueType);
1160     if (status != napi_ok || valueType != expectType) {
1161         return false;
1162     }
1163     return true;
1164 }
1165 
GetUndefinedValue(napi_env env)1166 napi_value NapiUtils::GetUndefinedValue(napi_env env)
1167 {
1168     napi_value result {};
1169     napi_get_undefined(env, &result);
1170     return result;
1171 }
1172 
GetPropertyNames(napi_env env,napi_value in,std::vector<std::string> & out)1173 napi_status NapiUtils::GetPropertyNames(napi_env env, napi_value in, std::vector<std::string>& out)
1174 {
1175     napi_value names {};
1176     NAPI_CALL_BASE(env, napi_get_property_names(env, in, &names), napi_generic_failure);
1177     uint32_t length = 0;
1178     NAPI_CALL_BASE(env, napi_get_array_length(env, names, &length), napi_generic_failure);
1179 
1180     for (uint32_t index = 0; index < length; ++index) {
1181         napi_value name {};
1182         std::string nameString;
1183         if (napi_get_element(env, names, index, &name) != napi_ok) {
1184             continue;
1185         }
1186         if (GetValue(env, name, nameString) != napi_ok) {
1187             continue;
1188         }
1189         out.push_back(nameString);
1190     }
1191 
1192     return napi_ok;
1193 }
1194 
GetDateValue(napi_env env,napi_value value,double & result)1195 napi_status NapiUtils::GetDateValue(napi_env env, napi_value value, double& result)
1196 {
1197     CHECK_RETURN(env != nullptr, "env is nullptr", napi_invalid_arg);
1198     CHECK_RETURN(value != nullptr, "value is nullptr", napi_invalid_arg);
1199 
1200     SLOGD("GetDateValue in");
1201     bool isDate = false;
1202     napi_is_date(env, value, &isDate);
1203     if (isDate) {
1204         napi_status status = napi_get_date_value(env, value, &result);
1205         if (status != napi_ok) {
1206             SLOGE("get date error");
1207         }
1208         SLOGD("GetDateValue out");
1209         return napi_ok;
1210     } else {
1211         SLOGE("value is not date type");
1212         return napi_date_expected;
1213     }
1214 }
1215 
SetDateValue(napi_env env,double time,napi_value & result)1216 napi_status NapiUtils::SetDateValue(napi_env env, double time, napi_value& result)
1217 {
1218     CHECK_RETURN(env != nullptr, "env is nullptr", napi_invalid_arg);
1219 
1220     SLOGD("SetDateValue in");
1221     napi_status status = napi_create_date(env, time, &result);
1222     if (status != napi_ok) {
1223         SLOGE("create date error");
1224     }
1225     SLOGD("SetDateValue out");
1226     return napi_ok;
1227 }
1228 
GetRefByCallback(napi_env env,std::list<napi_ref> callbackList,napi_value callback,napi_ref & callbackRef)1229 napi_status NapiUtils::GetRefByCallback(napi_env env, std::list<napi_ref> callbackList, napi_value callback,
1230                                         napi_ref& callbackRef)
1231 {
1232     for (auto ref = callbackList.begin(); ref != callbackList.end(); ++ref) {
1233         if (Equals(env, callback, *ref)) {
1234             SLOGD("Callback has been matched");
1235             callbackRef = *ref;
1236             break;
1237         }
1238     }
1239     return napi_ok;
1240 }
1241 
1242 /* napi_value is napi stage context */
GetStageElementName(napi_env env,napi_value in,AppExecFwk::ElementName & out)1243 napi_status NapiUtils::GetStageElementName(napi_env env, napi_value in, AppExecFwk::ElementName& out)
1244 {
1245     std::shared_ptr<AbilityRuntime::Context> stageContext = AbilityRuntime::GetStageModeContext(env, in);
1246     CHECK_RETURN(stageContext != nullptr, "get StagContext failed", napi_generic_failure);
1247     std::shared_ptr <AppExecFwk::AbilityInfo> abilityInfo;
1248     auto abilityContext = AbilityRuntime::Context::ConvertTo<AbilityRuntime::AbilityContext>(stageContext);
1249     if (abilityContext != nullptr) {
1250         abilityInfo = abilityContext->GetAbilityInfo();
1251     } else {
1252         auto extensionContext = AbilityRuntime::Context::ConvertTo<AbilityRuntime::ExtensionContext>(stageContext);
1253         CHECK_RETURN(extensionContext != nullptr, "context ConvertTo AbilityContext and ExtensionContext fail",
1254                      napi_generic_failure);
1255         abilityInfo = extensionContext->GetAbilityInfo();
1256     }
1257     out.SetBundleName(abilityInfo->bundleName);
1258     out.SetAbilityName(abilityInfo->name);
1259     return napi_ok;
1260 }
1261 
GetFaElementName(napi_env env,AppExecFwk::ElementName & out)1262 napi_status NapiUtils::GetFaElementName(napi_env env, AppExecFwk::ElementName& out)
1263 {
1264     auto* ability = AbilityRuntime::GetCurrentAbility(env);
1265     CHECK_RETURN(ability != nullptr, "get feature ability failed", napi_generic_failure);
1266     auto want = ability->GetWant();
1267     CHECK_RETURN(want != nullptr, "get want failed", napi_generic_failure);
1268     out = want->GetElement();
1269     return napi_ok;
1270 }
1271 
GetValue(napi_env env,napi_value in,AppExecFwk::ElementName & out)1272 napi_status NapiUtils::GetValue(napi_env env, napi_value in, AppExecFwk::ElementName& out)
1273 {
1274     bool isStageMode = false;
1275     CHECK_RETURN(AbilityRuntime::IsStageContext(env, in, isStageMode) == napi_ok, "get context type failed",
1276                  napi_generic_failure);
1277     if (isStageMode) {
1278         CHECK_RETURN(GetStageElementName(env, in, out) == napi_ok, "get StagContext failed", napi_generic_failure);
1279     } else {
1280         CHECK_RETURN(GetFaElementName(env, out) == napi_ok, "get FaContext failed", napi_generic_failure);
1281     }
1282     return napi_ok;
1283 }
1284 
GetValue(napi_env env,napi_value in,SessionToken & out)1285 napi_status NapiUtils::GetValue(napi_env env, napi_value in, SessionToken& out)
1286 {
1287     napi_value value {};
1288     auto status = napi_get_named_property(env, in, "sessionId", &value);
1289     CHECK_RETURN(status == napi_ok, "get SessionToken sessionId failed", status);
1290     status = GetValue(env, value, out.sessionId);
1291     CHECK_RETURN(status == napi_ok, "get SessionToken sessionId value failed", status);
1292 
1293     bool hasPid = false;
1294     NAPI_CALL_BASE(env, napi_has_named_property(env, in, "pid", &hasPid), napi_invalid_arg);
1295     if (hasPid) {
1296         status = napi_get_named_property(env, in, "pid", &value);
1297         CHECK_RETURN(status == napi_ok, "get SessionToken pid failed", status);
1298         status = GetValue(env, value, out.pid);
1299         CHECK_RETURN(status == napi_ok, "get SessionToken pid value failed", status);
1300     } else {
1301         out.pid = 0;
1302     }
1303 
1304     bool hasUid = false;
1305     NAPI_CALL_BASE(env, napi_has_named_property(env, in, "uid", &hasUid), napi_invalid_arg);
1306     if (hasUid) {
1307         status = napi_get_named_property(env, in, "uid", &value);
1308         CHECK_RETURN(status == napi_ok, "get SessionToken uid failed", status);
1309         status = GetValue(env, value, out.pid);
1310         CHECK_RETURN(status == napi_ok, "get SessionToken uid value failed", status);
1311     } else {
1312         out.uid = 0;
1313     }
1314     return napi_ok;
1315 }
1316 
GetValue(napi_env env,napi_value in,AudioStandard::DeviceRole & out)1317 napi_status NapiUtils::GetValue(napi_env env, napi_value in, AudioStandard::DeviceRole& out)
1318 {
1319     int32_t deviceRole;
1320     auto status = GetValue(env, in, deviceRole);
1321     CHECK_RETURN(status == napi_ok, "get AudioDeviceDescriptor deviceRole failed", status);
1322     out = static_cast<AudioStandard::DeviceRole>(deviceRole);
1323     return napi_ok;
1324 }
1325 
GetValue(napi_env env,napi_value in,AudioStandard::DeviceType & out)1326 napi_status NapiUtils::GetValue(napi_env env, napi_value in, AudioStandard::DeviceType& out)
1327 {
1328     int32_t deviceType;
1329     auto status = GetValue(env, in, deviceType);
1330     CHECK_RETURN(status == napi_ok, "get AudioDeviceDescriptor deviceType failed", status);
1331     out = static_cast<AudioStandard::DeviceType>(deviceType);
1332     return napi_ok;
1333 }
1334 
GetSampleRate(napi_env env,napi_value in,AudioStandard::AudioSamplingRate & out)1335 napi_status NapiUtils::GetSampleRate(napi_env env, napi_value in, AudioStandard::AudioSamplingRate& out)
1336 {
1337     napi_value value {};
1338     auto status = napi_get_named_property(env, in, "sampleRates", &value);
1339     uint32_t length {};
1340     napi_get_array_length(env, value, &length);
1341     CHECK_RETURN(status == napi_ok, "get array length failed", status);
1342     if (length > 0) {
1343         napi_value element {};
1344         status = napi_get_element(env, value, 0, &element);
1345         CHECK_RETURN((status == napi_ok) && (element != nullptr), "get element failed", status);
1346         int32_t samplingRate;
1347         status = GetValue(env, element, samplingRate);
1348         CHECK_RETURN(status == napi_ok, "get AudioDeviceDescriptor audioStreamInfo_ samplingRate value failed", status);
1349         out = static_cast<AudioStandard::AudioSamplingRate>(samplingRate);
1350     }
1351     return status;
1352 }
1353 
GetChannels(napi_env env,napi_value in,AudioStandard::AudioChannel & out)1354 napi_status NapiUtils::GetChannels(napi_env env, napi_value in, AudioStandard::AudioChannel& out)
1355 {
1356     napi_value value {};
1357     auto status = napi_get_named_property(env, in, "channelCounts", &value);
1358     uint32_t length {};
1359     napi_get_array_length(env, value, &length);
1360     CHECK_RETURN(status == napi_ok, "get array length failed", status);
1361     if (length > 0) {
1362         napi_value element {};
1363         status = napi_get_element(env, value, 0, &element);
1364         CHECK_RETURN((status == napi_ok) && (element != nullptr), "get element failed", status);
1365         int32_t channel;
1366         status = GetValue(env, element, channel);
1367         CHECK_RETURN(status == napi_ok, "get AudioDeviceDescriptor audioStreamInfo_ channels value failed", status);
1368         out = static_cast<AudioStandard::AudioChannel>(channel);
1369     }
1370     return status;
1371 }
1372 
GetChannelMasks(napi_env env,napi_value in,int32_t & out)1373 napi_status NapiUtils::GetChannelMasks(napi_env env, napi_value in, int32_t& out)
1374 {
1375     napi_value value {};
1376     auto status = napi_get_named_property(env, in, "channelMasks", &value);
1377     uint32_t length {};
1378     napi_get_array_length(env, value, &length);
1379     CHECK_RETURN(status == napi_ok, "get array length failed", status);
1380     if (length > 0) {
1381         napi_value element {};
1382         status = napi_get_element(env, value, 0, &element);
1383         CHECK_RETURN((status == napi_ok) && (element != nullptr), "get element failed", status);
1384         status = GetValue(env, element, out);
1385         CHECK_RETURN(status == napi_ok, "get AudioDeviceDescriptor channelMasks_ value failed", status);
1386     }
1387     return status;
1388 }
1389 
GetValue(napi_env env,napi_value in,AudioStandard::AudioDeviceDescriptor & out)1390 napi_status NapiUtils::GetValue(napi_env env, napi_value in, AudioStandard::AudioDeviceDescriptor& out)
1391 {
1392     napi_value value {};
1393     auto status = napi_get_named_property(env, in, "id", &value);
1394     CHECK_RETURN(status == napi_ok, "get AudioDeviceDescriptor deviceId_ failed", status);
1395     status = GetValue(env, value, out.deviceId_);
1396     CHECK_RETURN(status == napi_ok, "get AudioDeviceDescriptor deviceId_ value failed", status);
1397 
1398     status = napi_get_named_property(env, in, "name", &value);
1399     CHECK_RETURN(status == napi_ok, "get AudioDeviceDescriptor deviceName_ failed", status);
1400     status = GetValue(env, value, out.deviceName_);
1401     CHECK_RETURN(status == napi_ok, "get AudioDeviceDescriptor deviceName_ value failed", status);
1402 
1403     status = napi_get_named_property(env, in, "networkId", &value);
1404     CHECK_RETURN(status == napi_ok, "get AudioDeviceDescriptor networkId failed", status);
1405     status = GetValue(env, value, out.networkId_);
1406     CHECK_RETURN(status == napi_ok, "get AudioDeviceDescriptor networkId value failed", status);
1407 
1408     status = napi_get_named_property(env, in, "deviceRole", &value);
1409     CHECK_RETURN(status == napi_ok, "get AudioDeviceDescriptor deviceRole_ failed", status);
1410     status = GetValue(env, value, out.deviceRole_);
1411     CHECK_RETURN(status == napi_ok, "get AudioDeviceDescriptor deviceRole_ value failed", status);
1412 
1413     if (napi_get_named_property(env, in, "address", &value) == napi_ok) {
1414         GetValue(env, value, out.macAddress_);
1415     }
1416 
1417     if (napi_get_named_property(env, in, "deviceType", &value) == napi_ok) {
1418         GetValue(env, value, out.deviceType_);
1419     }
1420 
1421     if (napi_get_named_property(env, in, "interruptGroupId", &value) == napi_ok) {
1422         GetValue(env, value, out.interruptGroupId_);
1423     }
1424 
1425     if (napi_get_named_property(env, in, "volumeGroupId", &value) == napi_ok) {
1426         GetValue(env, value, out.volumeGroupId_);
1427     }
1428 
1429     AudioStandard::AudioSamplingRate audioSamplingRate;
1430     GetSampleRate(env, in, audioSamplingRate);
1431     out.audioStreamInfo_.samplingRate = {audioSamplingRate};
1432 
1433     AudioStandard::AudioChannel audioChannel;
1434     GetChannels(env, in, audioChannel);
1435     out.audioStreamInfo_.channels = {audioChannel};
1436 
1437     GetChannelMasks(env, in, out.channelMasks_);
1438     return napi_ok;
1439 }
1440 
GetValue(napi_env env,napi_value in,std::vector<AudioStandard::AudioDeviceDescriptor> & out)1441 napi_status NapiUtils::GetValue(napi_env env, napi_value in, std::vector<AudioStandard::AudioDeviceDescriptor>& out)
1442 {
1443     uint32_t length {};
1444     auto status = napi_get_array_length(env, in, &length);
1445     CHECK_RETURN(status == napi_ok, "get array length failed", status);
1446     for (uint32_t i = 0; i < length; ++i) {
1447         napi_value element {};
1448         status = napi_get_element(env, in, i, &element);
1449         CHECK_RETURN((status == napi_ok) && (element != nullptr), "get element failed", status);
1450         AudioStandard::AudioDeviceDescriptor descriptor;
1451         status = GetValue(env, element, descriptor);
1452         out.push_back(descriptor);
1453     }
1454     return napi_ok;
1455 }
1456 
GetOptionalString(napi_env env,napi_value in,DeviceInfo & out)1457 napi_status NapiUtils::GetOptionalString(napi_env env, napi_value in, DeviceInfo& out)
1458 {
1459     napi_value value {};
1460     bool hasIpAddress = false;
1461     napi_has_named_property(env, in, "ipAddress", &hasIpAddress);
1462     if (hasIpAddress) {
1463         napi_status status = napi_get_named_property(env, in, "ipAddress", &value);
1464         CHECK_RETURN(status == napi_ok, "get DeviceInfo ipAddress failed", status);
1465 
1466         napi_valuetype type = napi_undefined;
1467         status = napi_typeof(env, value, &type);
1468         CHECK_RETURN((status == napi_ok) && type == napi_string, "invalid typ for ipAddress", napi_invalid_arg);
1469 
1470         size_t maxLen = STR_MAX_LENGTH;
1471         status = napi_get_value_string_utf8(env, value, nullptr, 0, &maxLen);
1472         if (maxLen == 0) {
1473             out.ipAddress_ = "";
1474         } else {
1475             if (maxLen < 0 || maxLen >= STR_MAX_LENGTH) {
1476                 return napi_invalid_arg;
1477             }
1478             char buf[STR_MAX_LENGTH + STR_TAIL_LENGTH] {};
1479             size_t len = 0;
1480             status = napi_get_value_string_utf8(env, value, buf, maxLen + STR_TAIL_LENGTH, &len);
1481             if (status == napi_ok) {
1482                 out.ipAddress_ = std::string(buf);
1483             }
1484         }
1485         CHECK_RETURN(status == napi_ok, "get DeviceInfo ipAddress value failed", status);
1486     } else {
1487         out.ipAddress_ = "";
1488     }
1489     return napi_ok;
1490 }
1491 
1492 /* napi_value -> DeviceInfo */
GetValue(napi_env env,napi_value in,DeviceInfo & out)1493 napi_status NapiUtils::GetValue(napi_env env, napi_value in, DeviceInfo& out)
1494 {
1495     napi_value value {};
1496     auto status = napi_get_named_property(env, in, "castCategory", &value);
1497     CHECK_RETURN(status == napi_ok, "get DeviceInfo castCategory_ failed", status);
1498     status = GetValue(env, value, out.castCategory_);
1499     CHECK_RETURN(status == napi_ok, "get DeviceInfo castCategory_ value failed", status);
1500     status = napi_get_named_property(env, in, "deviceId", &value);
1501     CHECK_RETURN(status == napi_ok, "get DeviceInfo deviceId_ failed", status);
1502     status = GetValue(env, value, out.deviceId_);
1503     CHECK_RETURN(status == napi_ok, "get DeviceInfo deviceId_ value failed", status);
1504     status = napi_get_named_property(env, in, "manufacturer", &value);
1505     CHECK_RETURN(status == napi_ok, "get DeviceInfo manufacturer_ failed", status);
1506     status = GetValue(env, value, out.manufacturer_);
1507     CHECK_RETURN(status == napi_ok, "get DeviceInfo manufacturer_ value failed", status);
1508     status = napi_get_named_property(env, in, "modelName", &value);
1509     CHECK_RETURN(status == napi_ok, "get DeviceInfo modelName_ failed", status);
1510     status = GetValue(env, value, out.modelName_);
1511     CHECK_RETURN(status == napi_ok, "get DeviceInfo modelName_ value failed", status);
1512     status = napi_get_named_property(env, in, "deviceName", &value);
1513     CHECK_RETURN(status == napi_ok, "get DeviceInfo deviceName_ failed", status);
1514     status = GetValue(env, value, out.deviceName_);
1515     CHECK_RETURN(status == napi_ok, "get DeviceInfo deviceName_ value failed", status);
1516     status = napi_get_named_property(env, in, "deviceType", &value);
1517     CHECK_RETURN(status == napi_ok, "get DeviceInfo deviceType_ failed", status);
1518     status = GetValue(env, value, out.deviceType_);
1519     CHECK_RETURN(status == napi_ok, "get DeviceInfo deviceType_ value failed", status);
1520     CHECK_RETURN(GetOptionalString(env, in, out) == napi_ok, "get DeviceInfo ip address value failed", status);
1521 
1522     bool hasKey = false;
1523     napi_has_named_property(env, in, "providerId", &hasKey);
1524     if (hasKey) {
1525         status = napi_get_named_property(env, in, "providerId", &value);
1526         CHECK_RETURN(status == napi_ok, "get DeviceInfo providerId failed", status);
1527         status = GetValue(env, value, out.providerId_);
1528         CHECK_RETURN(status == napi_ok, "get DeviceInfo providerId value failed", status);
1529     } else {
1530         out.providerId_ = 0;
1531     }
1532 
1533     status = ProcessDeviceInfoParams(env, in, out);
1534     CHECK_RETURN(status == napi_ok, "get DeviceInfo ProcessDeviceInfoParams failed", status);
1535 
1536     return napi_ok;
1537 }
1538 
ProcessDeviceInfoParams(napi_env env,napi_value in,DeviceInfo & out)1539 napi_status NapiUtils::ProcessDeviceInfoParams(napi_env env, napi_value in, DeviceInfo& out)
1540 {
1541     napi_value value {};
1542     bool hasKey = false;
1543     napi_status status = napi_ok;
1544     napi_has_named_property(env, in, "supportedProtocols", &hasKey);
1545     if (hasKey) {
1546         status = napi_get_named_property(env, in, "supportedProtocols", &value);
1547         CHECK_RETURN(status == napi_ok, "get DeviceInfo supportedProtocols failed", status);
1548         status = GetValue(env, value, out.supportedProtocols_);
1549         CHECK_RETURN(status == napi_ok, "get DeviceInfo supportedProtocols value failed", status);
1550     } else {
1551         out.supportedProtocols_ = ProtocolType::TYPE_CAST_PLUS_STREAM;
1552     }
1553     napi_has_named_property(env, in, "authenticationStatus", &hasKey);
1554     if (hasKey) {
1555         status = napi_get_named_property(env, in, "authenticationStatus", &value);
1556         CHECK_RETURN(status == napi_ok, "get DeviceInfo authenticationStatus failed", status);
1557         status = GetValue(env, value, out.authenticationStatus_);
1558         CHECK_RETURN(status == napi_ok, "get DeviceInfo authenticationStatus value failed", status);
1559     } else {
1560         out.authenticationStatus_ = 0;
1561     }
1562     napi_has_named_property(env, in, "supportedDrmCapabilities", &hasKey);
1563     if (hasKey) {
1564         status = napi_get_named_property(env, in, "supportedDrmCapabilities", &value);
1565         CHECK_RETURN(status == napi_ok, "get DeviceInfo supportedDrmCapabilities failed", status);
1566         status = GetValue(env, value, out.supportedDrmCapabilities_);
1567         CHECK_RETURN(status == napi_ok, "get DeviceInfo supportedDrmCapabilities value failed", status);
1568     }
1569     napi_has_named_property(env, in, "isLegacy", &hasKey);
1570     if (hasKey) {
1571         status = napi_get_named_property(env, in, "isLegacy", &value);
1572         CHECK_RETURN(status == napi_ok, "get DeviceInfo isLegacy failed", status);
1573         status = GetValue(env, value, out.isLegacy_);
1574         CHECK_RETURN(status == napi_ok, "get DeviceInfo isLegacy value failed", status);
1575     } else {
1576         out.isLegacy_ = false;
1577     }
1578     napi_has_named_property(env, in, "mediumTypes", &hasKey);
1579     if (hasKey) {
1580         status = napi_get_named_property(env, in, "mediumTypes", &value);
1581         CHECK_RETURN(status == napi_ok, "get DeviceInfo mediumTypes failed", status);
1582         status = GetValue(env, value, out.mediumTypes_);
1583         CHECK_RETURN(status == napi_ok, "get DeviceInfo mediumTypes value failed", status);
1584     } else {
1585         out.mediumTypes_ = COAP;
1586     }
1587     return napi_ok;
1588 }
1589 
1590 /* napi_value -> OutputDeviceInfo */
GetValue(napi_env env,napi_value in,OutputDeviceInfo & out)1591 napi_status NapiUtils::GetValue(napi_env env, napi_value in, OutputDeviceInfo& out)
1592 {
1593     napi_value devices = nullptr;
1594     bool hasProperty = false;
1595     NAPI_CALL_BASE(env, napi_has_named_property(env, in, "devices", &hasProperty), napi_invalid_arg);
1596     if (!hasProperty) {
1597         SLOGE("devices is not exit in OutputDeviceInfo");
1598         return napi_invalid_arg;
1599     }
1600     NAPI_CALL_BASE(env, napi_get_named_property(env, in, "devices", &devices), napi_invalid_arg);
1601     bool isArray = false;
1602     NAPI_CALL_BASE(env, napi_is_array(env, devices, &isArray), napi_invalid_arg);
1603     if (!isArray) {
1604         SLOGE("devices is not array");
1605         return napi_invalid_arg;
1606     }
1607 
1608     uint32_t arrLen = 0;
1609     NAPI_CALL_BASE(env, napi_get_array_length(env, devices, &arrLen), napi_invalid_arg);
1610     if (arrLen == 0) {
1611         SLOGE("devices len is invalid");
1612         return napi_invalid_arg;
1613     }
1614 
1615     for (uint32_t i = 0; i < arrLen; i++) {
1616         napi_value item = nullptr;
1617         NAPI_CALL_BASE(env, napi_get_element(env, devices, i, &item), napi_invalid_arg);
1618         DeviceInfo deviceInfo;
1619         napi_status status = GetValue(env, item, deviceInfo);
1620         CHECK_RETURN(status == napi_ok, "not is device info", status);
1621         out.deviceInfos_.push_back(deviceInfo);
1622     }
1623     return napi_ok;
1624 }
1625 
1626 /* napi_value -> MediaInfoHolder */
GetValue(napi_env env,napi_value in,MediaInfoHolder & out)1627 napi_status NapiUtils::GetValue(napi_env env, napi_value in, MediaInfoHolder& out)
1628 {
1629     return NapiMediaInfoHolder::GetValue(env, in, out);
1630 }
1631 
1632 /* napi_value <-> MediaInfoHolder */
SetValue(napi_env env,const MediaInfoHolder & in,napi_value & out)1633 napi_status NapiUtils::SetValue(napi_env env, const MediaInfoHolder& in, napi_value& out)
1634 {
1635     return NapiMediaInfoHolder::SetValue(env, in, out);
1636 }
1637 
1638 /* napi_value -> MediaInfo */
GetValue(napi_env env,napi_value in,MediaInfo & out)1639 napi_status NapiUtils::GetValue(napi_env env, napi_value in, MediaInfo& out)
1640 {
1641     napi_value value {};
1642     auto status = napi_get_named_property(env, in, "mediaId", &value);
1643     CHECK_RETURN(status == napi_ok, "get mediaId failed", status);
1644     status = GetValue(env, value, out.mediaId_);
1645     CHECK_RETURN(status == napi_ok, "get mediaId value failed", status);
1646 
1647     status = napi_get_named_property(env, in, "mediaUrl", &value);
1648     CHECK_RETURN(status == napi_ok, "get mediaUrl failed", status);
1649     status = GetValue(env, value, out.mediaUrl_);
1650     CHECK_RETURN(status == napi_ok, "get mediaUrl value failed", status);
1651 
1652     bool hasStartPosition = false;
1653     napi_has_named_property(env, in, "startPosition", &hasStartPosition);
1654     if (hasStartPosition) {
1655         status = napi_get_named_property(env, in, "startPosition", &value);
1656         CHECK_RETURN(status == napi_ok, "get MediaInfo startPosition failed", status);
1657         status = GetValue(env, value, out.startPosition_);
1658         CHECK_RETURN(status == napi_ok, "get MediaInfo startPosition value failed", status);
1659     } else {
1660         out.startPosition_ = -1;
1661     }
1662     return napi_ok;
1663 }
1664 
1665 /* napi_value <- MediaInfo */
SetValue(napi_env env,const MediaInfo & in,napi_value & out)1666 napi_status NapiUtils::SetValue(napi_env env, const MediaInfo& in, napi_value& out)
1667 {
1668     napi_status status = napi_create_object(env, &out);
1669     CHECK_RETURN((status == napi_ok) && (out != nullptr), "create object failed", status);
1670 
1671     napi_value property = nullptr;
1672     status = SetValue(env, in.mediaId_, property);
1673     CHECK_RETURN((status == napi_ok) && (property != nullptr), "create object failed", status);
1674     status = napi_set_named_property(env, out, "mediaId", property);
1675     CHECK_RETURN(status == napi_ok, "napi_set_named_property failed", status);
1676 
1677     status = SetValue(env, in.mediaUrl_, property);
1678     CHECK_RETURN((status == napi_ok) && (property != nullptr), "create object failed", status);
1679     status = napi_set_named_property(env, out, "mediaUrl", property);
1680     CHECK_RETURN(status == napi_ok, "napi_set_named_property failed", status);
1681 
1682     if (in.startPosition_ != -1) {
1683         status = SetValue(env, in.startPosition_, property);
1684         CHECK_RETURN((status == napi_ok) && (property != nullptr), "create object failed", status);
1685         status = napi_set_named_property(env, out, "mediaInfo", property);
1686         CHECK_RETURN(status == napi_ok, "napi_set_named_property failed", status);
1687     }
1688 
1689     return napi_ok;
1690 }
1691 
1692 /* napi_value -> AVFileDescriptor */
GetValue(napi_env env,napi_value in,AVFileDescriptor & out)1693 napi_status NapiUtils::GetValue(napi_env env, napi_value in, AVFileDescriptor& out)
1694 {
1695     napi_value value {};
1696     auto status = napi_ok;
1697     bool hasFd = false;
1698     napi_has_named_property(env, in, "fd", &hasFd);
1699     if (hasFd) {
1700         status = napi_get_named_property(env, in, "fd", &value);
1701         CHECK_RETURN(status == napi_ok, "get fd failed", status);
1702         status = GetValue(env, value, out.fd_);
1703         CHECK_RETURN(status == napi_ok, "get fd value failed", status);
1704     } else {
1705         out.fd_ = 0;
1706     }
1707 
1708     bool hasOffset = false;
1709     napi_has_named_property(env, in, "offset", &hasOffset);
1710     if (hasOffset) {
1711         status = napi_get_named_property(env, in, "offset", &value);
1712         CHECK_RETURN(status == napi_ok, "get offset failed", status);
1713         status = GetValue(env, value, out.offset_);
1714         CHECK_RETURN(status == napi_ok, "get offset value failed", status);
1715     } else {
1716         out.offset_ = 0;
1717     }
1718 
1719     bool hasLength = false;
1720     napi_has_named_property(env, in, "length", &hasLength);
1721     if (hasLength) {
1722         status = napi_get_named_property(env, in, "length", &value);
1723         CHECK_RETURN(status == napi_ok, "get length failed", status);
1724         status = GetValue(env, value, out.length_);
1725         CHECK_RETURN(status == napi_ok, "get length value failed", status);
1726     } else {
1727         out.length_ = -1;
1728     }
1729     return napi_ok;
1730 }
1731 
1732 /* napi_value <- AVFileDescriptor */
SetValue(napi_env env,const AVFileDescriptor & in,napi_value & out)1733 napi_status NapiUtils::SetValue(napi_env env, const AVFileDescriptor& in, napi_value& out)
1734 {
1735     napi_status status = napi_create_object(env, &out);
1736     CHECK_RETURN((status == napi_ok) && (out != nullptr), "create object failed", status);
1737 
1738     napi_value property = nullptr;
1739     status = SetValue(env, in.fd_, property);
1740     CHECK_RETURN((status == napi_ok) && (property != nullptr), "create object failed", status);
1741     status = napi_set_named_property(env, out, "fd", property);
1742     CHECK_RETURN(status == napi_ok, "napi_set_named_property failed", status);
1743 
1744     if (in.offset_ != 0) {
1745         status = SetValue(env, in.offset_, property);
1746         CHECK_RETURN((status == napi_ok) && (property != nullptr), "create object failed", status);
1747         status = napi_set_named_property(env, out, "offset", property);
1748         CHECK_RETURN(status == napi_ok, "napi_set_named_property failed", status);
1749     }
1750 
1751     if (in.length_ != -1) {
1752         status = SetValue(env, in.length_, property);
1753         CHECK_RETURN((status == napi_ok) && (property != nullptr), "create object failed", status);
1754         status = napi_set_named_property(env, out, "length", property);
1755         CHECK_RETURN(status == napi_ok, "napi_set_named_property failed", status);
1756     }
1757     return napi_ok;
1758 }
1759 
ThrowError(napi_env env,const char * napiMessage,int32_t napiCode)1760 napi_status NapiUtils::ThrowError(napi_env env, const char* napiMessage, int32_t napiCode)
1761 {
1762     napi_value message = nullptr;
1763     napi_value code = nullptr;
1764     napi_value result = nullptr;
1765     napi_create_string_utf8(env, napiMessage, NAPI_AUTO_LENGTH, &message);
1766     napi_create_error(env, nullptr, message, &result);
1767     napi_create_int32(env, napiCode, &code);
1768     napi_set_named_property(env, result, "code", code);
1769     napi_throw(env, result);
1770     return napi_ok;
1771 }
1772 }
1773