1 /*
2  * Copyright (C) 2021 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 "common_napi.h"
17 #include <climits>
18 #include "avcodec_list.h"
19 #include "media_log.h"
20 #include "media_errors.h"
21 
22 namespace {
23     constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_PLAYER, "CommonNapi"};
24 }
25 
26 namespace OHOS {
27 namespace Media {
GetStringArgument(napi_env env,napi_value value,size_t maxLength)28 std::string CommonNapi::GetStringArgument(napi_env env, napi_value value, size_t maxLength)
29 {
30     std::string strValue = "";
31     size_t bufLength = 0;
32     napi_status status = napi_get_value_string_utf8(env, value, nullptr, 0, &bufLength);
33     if (status == napi_ok && bufLength > 0 && bufLength < maxLength) {
34         char *buffer = static_cast<char *>(malloc((bufLength + 1) * sizeof(char)));
35         CHECK_AND_RETURN_RET_LOG(buffer != nullptr, strValue, "no memory");
36         status = napi_get_value_string_utf8(env, value, buffer, bufLength + 1, &bufLength);
37         if (status == napi_ok) {
38             MEDIA_LOGD("argument = %{public}s", buffer);
39             strValue = buffer;
40         }
41         free(buffer);
42         buffer = nullptr;
43     }
44     return strValue;
45 }
46 
CheckValueType(napi_env env,napi_value arg,napi_valuetype type)47 bool CommonNapi::CheckValueType(napi_env env, napi_value arg, napi_valuetype type)
48 {
49     napi_valuetype valueType = napi_undefined;
50     if (arg != nullptr && napi_typeof(env, arg, &valueType) == napi_ok && valueType == type) {
51         return true;
52     }
53     return false;
54 }
55 
CheckhasNamedProperty(napi_env env,napi_value arg,std::string type)56 bool CommonNapi::CheckhasNamedProperty(napi_env env, napi_value arg, std::string type)
57 {
58     bool exist = false;
59     napi_status napiStatus = napi_has_named_property(env, arg, type.c_str(), &exist);
60     return exist && (napiStatus == napi_ok);
61 }
62 
GetPropertyInt32(napi_env env,napi_value configObj,const std::string & type,int32_t & result)63 bool CommonNapi::GetPropertyInt32(napi_env env, napi_value configObj, const std::string &type, int32_t &result)
64 {
65     napi_value item = nullptr;
66     bool exist = false;
67     napi_status napiStatus = napi_has_named_property(env, configObj, type.c_str(), &exist);
68     CHECK_AND_RETURN_RET_LOG(napiStatus == napi_ok && exist, false, "can not find %{public}s property", type.c_str());
69     CHECK_AND_RETURN_RET_LOG(napi_get_named_property(env, configObj, type.c_str(), &item) == napi_ok, false,
70         "get %{public}s property fail", type.c_str());
71     CHECK_AND_RETURN_RET_LOG(napi_get_value_int32(env, item, &result) == napi_ok, false,
72         "get %{public}s property value fail", type.c_str());
73     return true;
74 }
75 
GetPropertyUint32(napi_env env,napi_value configObj,const std::string & type,uint32_t & result)76 bool CommonNapi::GetPropertyUint32(napi_env env, napi_value configObj, const std::string &type, uint32_t &result)
77 {
78     napi_value item = nullptr;
79     bool exist = false;
80     napi_status status = napi_has_named_property(env, configObj, type.c_str(), &exist);
81     CHECK_AND_RETURN_RET_LOG(status == napi_ok && exist, false, "can not find %{public}s property", type.c_str());
82     CHECK_AND_RETURN_RET_LOG(napi_get_named_property(env, configObj, type.c_str(), &item) == napi_ok, false,
83         "get %{public}s property fail", type.c_str());
84 
85     CHECK_AND_RETURN_RET_LOG(napi_get_value_uint32(env, item, &result) == napi_ok, false,
86         "get %{public}s property value fail", type.c_str());
87     return true;
88 }
89 
GetPropertyInt64(napi_env env,napi_value configObj,const std::string & type,int64_t & result)90 bool CommonNapi::GetPropertyInt64(napi_env env, napi_value configObj, const std::string &type, int64_t &result)
91 {
92     napi_value item = nullptr;
93     bool exist = false;
94     napi_status status = napi_has_named_property(env, configObj, type.c_str(), &exist);
95     if (status != napi_ok || !exist) {
96         MEDIA_LOGE("can not find %{public}s property", type.c_str());
97         return false;
98     }
99 
100     if (napi_get_named_property(env, configObj, type.c_str(), &item) != napi_ok) {
101         MEDIA_LOGE("get %{public}s property fail", type.c_str());
102         return false;
103     }
104 
105     if (napi_get_value_int64(env, item, &result) != napi_ok) {
106         MEDIA_LOGE("get %{public}s property value fail", type.c_str());
107         return false;
108     }
109     return true;
110 }
111 
GetPropertyDouble(napi_env env,napi_value configObj,const std::string & type,double & result)112 bool CommonNapi::GetPropertyDouble(napi_env env, napi_value configObj, const std::string &type, double &result)
113 {
114     napi_value item = nullptr;
115     bool exist = false;
116     napi_status status = napi_has_named_property(env, configObj, type.c_str(), &exist);
117     if (status != napi_ok || !exist) {
118         MEDIA_LOGE("can not find %{public}s property", type.c_str());
119         return false;
120     }
121 
122     if (napi_get_named_property(env, configObj, type.c_str(), &item) != napi_ok) {
123         MEDIA_LOGE("get %{public}s property fail", type.c_str());
124         return false;
125     }
126 
127     if (napi_get_value_double(env, item, &result) != napi_ok) {
128         MEDIA_LOGE("get %{public}s property value fail", type.c_str());
129         return false;
130     }
131     return true;
132 }
133 
GetPropertyString(napi_env env,napi_value configObj,const std::string & type)134 std::string CommonNapi::GetPropertyString(napi_env env, napi_value configObj, const std::string &type)
135 {
136     std::string invalid = "";
137     bool exist = false;
138     napi_status status = napi_has_named_property(env, configObj, type.c_str(), &exist);
139     if (status != napi_ok || !exist) {
140         MEDIA_LOGE("can not find %{public}s property", type.c_str());
141         return invalid;
142     }
143 
144     napi_value item = nullptr;
145     if (napi_get_named_property(env, configObj, type.c_str(), &item) != napi_ok) {
146         MEDIA_LOGE("get %{public}s property fail", type.c_str());
147         return invalid;
148     }
149 
150     return GetStringArgument(env, item);
151 }
152 
GetPropertyRecord(napi_env env,napi_value configObj,Meta & meta,std::string type)153 napi_status CommonNapi::GetPropertyRecord(napi_env env, napi_value configObj, Meta &meta, std::string type)
154 {
155     bool exist = false;
156     napi_value in = nullptr;
157     napi_valuetype valueType = napi_undefined;
158     napi_status status = napi_has_named_property(env, configObj, type.c_str(), &exist);
159     if (status != napi_ok || !exist) {
160         MEDIA_LOGE("can not find %{public}s property", type.c_str());
161         return napi_invalid_arg;
162     }
163     if (napi_get_named_property(env, configObj, type.c_str(), &in) != napi_ok) {
164         MEDIA_LOGE("get %{public}s property fail", type.c_str());
165         return napi_invalid_arg;
166     }
167     status = napi_typeof(env, in, &valueType);
168     CHECK_AND_RETURN_RET_LOG(status == napi_ok, status, "get valueType failed");
169     CHECK_AND_RETURN_RET_LOG(valueType != napi_undefined, napi_ok, "PropertyRecord undefined");
170     CHECK_AND_RETURN_RET_LOG(valueType == napi_object, napi_invalid_arg, "invalid arguments");
171 
172     napi_value dataList = nullptr;
173     uint32_t count = 0;
174     status = napi_get_property_names(env, in, &dataList);
175     CHECK_AND_RETURN_RET_LOG(status == napi_ok, status, "get property names failed");
176     status = napi_get_array_length(env, dataList, &count);
177     CHECK_AND_RETURN_RET_LOG(status == napi_ok && count <= MAX_COUNT,
178         napi_invalid_arg, "get length failed or more than 500");
179 
180     napi_value jsKey = nullptr;
181     napi_value jsValue = nullptr;
182     for (uint32_t i = 0; i < count; i++) {
183         status = napi_get_element(env, dataList, i, &jsKey);
184         CHECK_AND_RETURN_RET_LOG(status == napi_ok, status, "get element Key failed");
185         status = napi_typeof(env, jsKey, &valueType);
186         CHECK_AND_RETURN_RET_LOG(status == napi_ok, status, "get valueType failed");
187         CHECK_AND_RETURN_RET_LOG(valueType == napi_string, napi_invalid_arg, "key not supported type");
188         std::string strKey = GetStringArgument(env, jsKey, CUSTOM_MAX_LENGTH);
189         CHECK_AND_RETURN_RET_LOG(strKey != "", napi_invalid_arg, "key not supported");
190 
191         status = napi_get_named_property(env, in, strKey.c_str(), &jsValue);
192         CHECK_AND_RETURN_RET_LOG(status == napi_ok, status, "get property value failed");
193         status = napi_typeof(env, jsValue, &valueType);
194         CHECK_AND_RETURN_RET_LOG(status == napi_ok, status, "get valueType failed");
195 
196         CHECK_AND_RETURN_RET_LOG(valueType == napi_string, napi_invalid_arg, "value not supported type");
197         std::string strValue = GetStringArgument(env, jsValue, CUSTOM_MAX_LENGTH);
198         CHECK_AND_RETURN_RET_LOG(!strValue.empty(), napi_invalid_arg, "get value failed");
199         meta.SetData(strKey, strValue);
200     }
201     return napi_ok;
202 }
203 
GetFdArgument(napi_env env,napi_value value,AVFileDescriptor & rawFd)204 bool CommonNapi::GetFdArgument(napi_env env, napi_value value, AVFileDescriptor &rawFd)
205 {
206     CHECK_AND_RETURN_RET(GetPropertyInt32(env, value, "fd", rawFd.fd) == true, false);
207 
208     if (!GetPropertyInt64(env, value, "offset", rawFd.offset)) {
209         rawFd.offset = 0; // use default value
210     }
211 
212     if (!GetPropertyInt64(env, value, "length", rawFd.length)) {
213         rawFd.length = -1; // -1 means use default value
214     }
215 
216     MEDIA_LOGD("get fd argument, fd = %{public}d, offset = %{public}" PRIi64 ", size = %{public}" PRIi64 "",
217         rawFd.fd, rawFd.offset, rawFd.length);
218 
219     return true;
220 }
221 
GetPropertyMap(napi_env env,napi_value value,std::map<std::string,std::string> & map)222 bool CommonNapi::GetPropertyMap(napi_env env, napi_value value, std::map<std::string, std::string>& map)
223 {
224     napi_value jsProNameList = nullptr;
225     uint32_t jsProCount = 0;
226     napi_status status = napi_get_property_names(env, value, &jsProNameList);
227     CHECK_AND_RETURN_RET_LOG(status == napi_ok, false, "get property name failed");
228     status = napi_get_array_length(env, jsProNameList, &jsProCount);
229     CHECK_AND_RETURN_RET_LOG(status == napi_ok, false, "get subKeys length failed");
230 
231     napi_value jsProName = nullptr;
232     napi_value jsProValue = nullptr;
233     for (uint32_t i = 0; i < jsProCount; i++) {
234         status = napi_get_element(env, jsProNameList, i, &jsProName);
235         CHECK_AND_RETURN_RET_LOG(status == napi_ok, false, "get sub key failed");
236         std::string strProName = GetStringArgument(env, jsProName);
237 
238         status = napi_get_named_property(env, value, strProName.c_str(), &jsProValue);
239         CHECK_AND_RETURN_RET_LOG(status == napi_ok, false, "get sub value failed");
240         std::string strProValue = GetStringArgument(env, jsProValue);
241 
242         map.emplace(strProName, strProValue);
243     }
244 
245     return true;
246 }
247 
GetPlayStrategy(napi_env env,napi_value value,AVPlayStrategyTmp & playStrategy)248 bool CommonNapi::GetPlayStrategy(napi_env env, napi_value value, AVPlayStrategyTmp &playStrategy)
249 {
250     if (!GetPropertyUint32(env, value, "preferredWidth", playStrategy.preferredWidth)) {
251         playStrategy.preferredWidth = 0; // use default value
252     }
253     if (!GetPropertyUint32(env, value, "preferredHeight", playStrategy.preferredHeight)) {
254         playStrategy.preferredHeight = 0; // use default value
255     }
256     if (!GetPropertyUint32(env, value, "preferredBufferDuration", playStrategy.preferredBufferDuration)) {
257         playStrategy.preferredBufferDuration = 0; // use default value
258     }
259     if (!GetPropertyBool(env, value, "preferredHdr", playStrategy.preferredHdr)) {
260         playStrategy.preferredHdr = 0; // use default value
261     }
262     if (!GetPropertyInt32(env, value, "mutedMediaType", playStrategy.mutedMediaType)) {
263         playStrategy.mutedMediaType = MediaType::MEDIA_TYPE_MAX_COUNT; // use default value
264     }
265     playStrategy.preferredAudioLanguage = GetPropertyString(env, value, "preferredAudioLanguage");
266     playStrategy.preferredSubtitleLanguage = GetPropertyString(env, value, "preferredSubtitleLanguage");
267     return true;
268 }
269 
FillErrorArgs(napi_env env,int32_t errCode,const napi_value & args)270 napi_status CommonNapi::FillErrorArgs(napi_env env, int32_t errCode, const napi_value &args)
271 {
272     napi_value codeStr = nullptr;
273     napi_status status = napi_create_string_utf8(env, "code", NAPI_AUTO_LENGTH, &codeStr);
274     CHECK_AND_RETURN_RET_LOG(status == napi_ok && codeStr != nullptr, napi_invalid_arg, "create code str fail");
275 
276     napi_value errCodeVal = nullptr;
277     int32_t errCodeInt = errCode;
278     status = napi_create_int32(env, errCodeInt, &errCodeVal);
279     CHECK_AND_RETURN_RET_LOG(status == napi_ok && errCodeVal != nullptr, napi_invalid_arg,
280         "create error code number val fail");
281 
282     status = napi_set_property(env, args, codeStr, errCodeVal);
283     CHECK_AND_RETURN_RET_LOG(status == napi_ok, napi_invalid_arg, "set error code property fail");
284 
285     napi_value nameStr = nullptr;
286     status = napi_create_string_utf8(env, "name", NAPI_AUTO_LENGTH, &nameStr);
287     CHECK_AND_RETURN_RET_LOG(status == napi_ok && nameStr != nullptr, napi_invalid_arg, "create name str fail");
288 
289     napi_value errNameVal = nullptr;
290     status = napi_create_string_utf8(env, "BusinessError", NAPI_AUTO_LENGTH, &errNameVal);
291     CHECK_AND_RETURN_RET_LOG(status == napi_ok && errNameVal != nullptr, napi_invalid_arg,
292         "create BusinessError str fail");
293 
294     status = napi_set_property(env, args, nameStr, errNameVal);
295     CHECK_AND_RETURN_RET_LOG(status == napi_ok, napi_invalid_arg, "set error name property fail");
296     return napi_ok;
297 }
298 
CreateError(napi_env env,int32_t errCode,const std::string & errMsg,napi_value & errVal)299 napi_status CommonNapi::CreateError(napi_env env, int32_t errCode, const std::string &errMsg, napi_value &errVal)
300 {
301     napi_get_undefined(env, &errVal);
302 
303     napi_value msgValStr = nullptr;
304     napi_status nstatus = napi_create_string_utf8(env, errMsg.c_str(), NAPI_AUTO_LENGTH, &msgValStr);
305     if (nstatus != napi_ok || msgValStr == nullptr) {
306         MEDIA_LOGE("create error message str fail");
307         return napi_invalid_arg;
308     }
309 
310     nstatus = napi_create_error(env, nullptr, msgValStr, &errVal);
311     if (nstatus != napi_ok || errVal == nullptr) {
312         MEDIA_LOGE("create error fail");
313         return napi_invalid_arg;
314     }
315 
316     napi_value codeStr = nullptr;
317     nstatus = napi_create_string_utf8(env, "code", NAPI_AUTO_LENGTH, &codeStr);
318     if (nstatus != napi_ok || codeStr == nullptr) {
319         MEDIA_LOGE("create code str fail");
320         return napi_invalid_arg;
321     }
322 
323     napi_value errCodeVal = nullptr;
324     nstatus = napi_create_int32(env, errCode, &errCodeVal);
325     if (nstatus != napi_ok || errCodeVal == nullptr) {
326         MEDIA_LOGE("create error code number val fail");
327         return napi_invalid_arg;
328     }
329 
330     nstatus = napi_set_property(env, errVal, codeStr, errCodeVal);
331     if (nstatus != napi_ok) {
332         MEDIA_LOGE("set error code property fail");
333         return napi_invalid_arg;
334     }
335 
336     napi_value nameStr = nullptr;
337     nstatus = napi_create_string_utf8(env, "name", NAPI_AUTO_LENGTH, &nameStr);
338     if (nstatus != napi_ok || nameStr == nullptr) {
339         MEDIA_LOGE("create name str fail");
340         return napi_invalid_arg;
341     }
342 
343     napi_value errNameVal = nullptr;
344     nstatus = napi_create_string_utf8(env, "BusinessError", NAPI_AUTO_LENGTH, &errNameVal);
345     if (nstatus != napi_ok || errNameVal == nullptr) {
346         MEDIA_LOGE("create BusinessError str fail");
347         return napi_invalid_arg;
348     }
349 
350     nstatus = napi_set_property(env, errVal, nameStr, errNameVal);
351     if (nstatus != napi_ok) {
352         MEDIA_LOGE("set error name property fail");
353         return napi_invalid_arg;
354     }
355 
356     return napi_ok;
357 }
358 
CreateReference(napi_env env,napi_value arg)359 napi_ref CommonNapi::CreateReference(napi_env env, napi_value arg)
360 {
361     napi_ref ref = nullptr;
362     napi_valuetype valueType = napi_undefined;
363     if (arg != nullptr && napi_typeof(env, arg, &valueType) == napi_ok && valueType == napi_function) {
364         MEDIA_LOGD("napi_create_reference");
365         napi_create_reference(env, arg, 1, &ref);
366     }
367     return ref;
368 }
369 
CreatePromise(napi_env env,napi_ref ref,napi_value & result)370 napi_deferred CommonNapi::CreatePromise(napi_env env, napi_ref ref, napi_value &result)
371 {
372     napi_deferred deferred = nullptr;
373     if (ref == nullptr) {
374         MEDIA_LOGD("napi_create_promise");
375         napi_create_promise(env, &deferred, &result);
376     }
377     return deferred;
378 }
379 
SetPropertyByValueType(napi_env env,napi_value & obj,std::shared_ptr<Meta> & meta,std::string key)380 bool CommonNapi::SetPropertyByValueType(napi_env env, napi_value &obj, std::shared_ptr<Meta> &meta, std::string key)
381 {
382     CHECK_AND_RETURN_RET(obj != nullptr && meta != nullptr, false);
383     CHECK_AND_RETURN_RET(meta->Find(key) != meta->end(), false);
384 
385     bool ret = true;
386     AnyValueType type = meta->GetValueType(key);
387     if (type == AnyValueType::STRING) {
388         std::string sValue;
389         ret = meta->GetData(key, sValue);
390         CHECK_AND_RETURN_RET_LOG(ret, ret, "GetData failed, key %{public}s", key.c_str());
391         ret = CommonNapi::SetPropertyString(env, obj, key, sValue);
392         CHECK_AND_RETURN_RET_LOG(ret, ret, "SetPropertyString failed, key %{public}s", key.c_str());
393     } else if (type == AnyValueType::INT32_T) {
394         int32_t value;
395         ret = meta->GetData(key, value);
396         CHECK_AND_RETURN_RET_LOG(ret, ret, "GetData failed, key %{public}s", key.c_str());
397         ret = CommonNapi::SetPropertyInt32(env, obj, key, value);
398         CHECK_AND_RETURN_RET_LOG(ret, ret, "SetPropertyString failed, key %{public}s", key.c_str());
399     } else if (type == AnyValueType::FLOAT) {
400         float dValue;
401         ret = meta->GetData(key, dValue);
402         CHECK_AND_RETURN_RET_LOG(ret, ret, "GetData failed, key %{public}s", key.c_str());
403         ret = CommonNapi::SetPropertyDouble(env, obj, key, dValue);
404         CHECK_AND_RETURN_RET_LOG(ret, ret, "SetPropertyString failed, key %{public}s", key.c_str());
405     } else {
406         MEDIA_LOGE("not supported value type");
407     }
408     return true;
409 }
410 
AddRangeProperty(napi_env env,napi_value obj,const std::string & name,int32_t min,int32_t max)411 bool CommonNapi::AddRangeProperty(napi_env env, napi_value obj, const std::string &name, int32_t min, int32_t max)
412 {
413     CHECK_AND_RETURN_RET(obj != nullptr, false);
414 
415     napi_value range = nullptr;
416     napi_status status = napi_create_object(env, &range);
417     CHECK_AND_RETURN_RET(status == napi_ok, false);
418 
419     CHECK_AND_RETURN_RET(SetPropertyInt32(env, range, "min", min) == true, false);
420     CHECK_AND_RETURN_RET(SetPropertyInt32(env, range, "max", max) == true, false);
421 
422     napi_value nameStr = nullptr;
423     status = napi_create_string_utf8(env, name.c_str(), NAPI_AUTO_LENGTH, &nameStr);
424     CHECK_AND_RETURN_RET(status == napi_ok, false);
425 
426     status = napi_set_property(env, obj, nameStr, range);
427     CHECK_AND_RETURN_RET(status == napi_ok, false);
428 
429     return true;
430 }
431 
AddArrayProperty(napi_env env,napi_value obj,const std::string & name,const std::vector<int32_t> & vec)432 bool CommonNapi::AddArrayProperty(napi_env env, napi_value obj, const std::string &name,
433     const std::vector<int32_t> &vec)
434 {
435     CHECK_AND_RETURN_RET(obj != nullptr, false);
436 
437     napi_value array = nullptr;
438     napi_status status = napi_create_array_with_length(env, vec.size(), &array);
439     CHECK_AND_RETURN_RET(status == napi_ok, false);
440 
441     for (uint32_t i = 0; i < vec.size(); i++) {
442         napi_value number = nullptr;
443         (void)napi_create_int32(env, vec.at(i), &number);
444         (void)napi_set_element(env, array, i, number);
445     }
446 
447     napi_value nameStr = nullptr;
448     status = napi_create_string_utf8(env, name.c_str(), NAPI_AUTO_LENGTH, &nameStr);
449     CHECK_AND_RETURN_RET(status == napi_ok, false);
450 
451     status = napi_set_property(env, obj, nameStr, array);
452     CHECK_AND_RETURN_RET(status == napi_ok, false);
453 
454     return true;
455 }
456 
AddArrayInt(napi_env env,napi_value & array,const std::vector<int32_t> & vec)457 bool CommonNapi::AddArrayInt(napi_env env, napi_value &array, const std::vector<int32_t> &vec)
458 {
459     if (vec.size() == 0) {
460         return false;
461     }
462 
463     napi_status status = napi_create_array_with_length(env, vec.size(), &array);
464     CHECK_AND_RETURN_RET(status == napi_ok, false);
465 
466     for (uint32_t i = 0; i < vec.size(); i++) {
467         napi_value number = nullptr;
468         (void)napi_create_int32(env, vec.at(i), &number);
469         (void)napi_set_element(env, array, i, number);
470     }
471 
472     return true;
473 }
474 
SetPropertyInt32(napi_env env,napi_value & obj,const std::string & key,int32_t value)475 bool CommonNapi::SetPropertyInt32(napi_env env, napi_value &obj, const std::string &key, int32_t value)
476 {
477     CHECK_AND_RETURN_RET(obj != nullptr, false);
478 
479     napi_value keyNapi = nullptr;
480     napi_status status = napi_create_string_utf8(env, key.c_str(), NAPI_AUTO_LENGTH, &keyNapi);
481     CHECK_AND_RETURN_RET(status == napi_ok, false);
482 
483     napi_value valueNapi = nullptr;
484     status = napi_create_int32(env, value, &valueNapi);
485     CHECK_AND_RETURN_RET(status == napi_ok, false);
486 
487     status = napi_set_property(env, obj, keyNapi, valueNapi);
488     CHECK_AND_RETURN_RET_LOG(status == napi_ok, false, "failed to set property");
489 
490     return true;
491 }
492 
SetPropertyInt64(napi_env env,napi_value & obj,const std::string & key,int64_t value)493 bool CommonNapi::SetPropertyInt64(napi_env env, napi_value &obj, const std::string &key, int64_t value)
494 {
495     CHECK_AND_RETURN_RET(obj != nullptr, false);
496 
497     napi_value keyNapi = nullptr;
498     napi_status status = napi_create_string_utf8(env, key.c_str(), NAPI_AUTO_LENGTH, &keyNapi);
499     CHECK_AND_RETURN_RET(status == napi_ok, false);
500 
501     napi_value valueNapi = nullptr;
502     status = napi_create_int64(env, value, &valueNapi);
503     CHECK_AND_RETURN_RET(status == napi_ok, false);
504 
505     status = napi_set_property(env, obj, keyNapi, valueNapi);
506     CHECK_AND_RETURN_RET_LOG(status == napi_ok, false, "failed to set property");
507 
508     return true;
509 }
510 
SetPropertyDouble(napi_env env,napi_value & obj,const std::string & key,double value)511 bool CommonNapi::SetPropertyDouble(napi_env env, napi_value &obj, const std::string &key, double value)
512 {
513     CHECK_AND_RETURN_RET(obj != nullptr, false);
514 
515     napi_value keyNapi = nullptr;
516     napi_status status = napi_create_string_utf8(env, key.c_str(), NAPI_AUTO_LENGTH, &keyNapi);
517     CHECK_AND_RETURN_RET(status == napi_ok, false);
518 
519     napi_value valueNapi = nullptr;
520     status = napi_create_double(env, value, &valueNapi);
521     CHECK_AND_RETURN_RET(status == napi_ok, false);
522 
523     status = napi_set_property(env, obj, keyNapi, valueNapi);
524     CHECK_AND_RETURN_RET_LOG(status == napi_ok, false, "failed to set property");
525 
526     return true;
527 }
528 
SetPropertyBool(napi_env env,napi_value & obj,const std::string & key,bool value)529 bool CommonNapi::SetPropertyBool(napi_env env, napi_value &obj, const std::string &key, bool value)
530 {
531     CHECK_AND_RETURN_RET(obj != nullptr, false);
532 
533     napi_value keyNapi = nullptr;
534     napi_status status = napi_create_string_utf8(env, key.c_str(), NAPI_AUTO_LENGTH, &keyNapi);
535     CHECK_AND_RETURN_RET(status == napi_ok, false);
536 
537     napi_value valueNapi = nullptr;
538     status = napi_get_boolean(env, value, &valueNapi);
539     CHECK_AND_RETURN_RET(status == napi_ok, false);
540 
541     status = napi_set_property(env, obj, keyNapi, valueNapi);
542     CHECK_AND_RETURN_RET_LOG(status == napi_ok, false, "failed to set property");
543 
544     return true;
545 }
546 
SetPropertyString(napi_env env,napi_value & obj,const std::string & key,const std::string & value)547 bool CommonNapi::SetPropertyString(napi_env env, napi_value &obj, const std::string &key, const std::string &value)
548 {
549     CHECK_AND_RETURN_RET(obj != nullptr, false);
550 
551     napi_value keyNapi = nullptr;
552     napi_status status = napi_create_string_utf8(env, key.c_str(), NAPI_AUTO_LENGTH, &keyNapi);
553     CHECK_AND_RETURN_RET(status == napi_ok, false);
554 
555     napi_value valueNapi = nullptr;
556     status = napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &valueNapi);
557     CHECK_AND_RETURN_RET(status == napi_ok, false);
558 
559     status = napi_set_property(env, obj, keyNapi, valueNapi);
560     CHECK_AND_RETURN_RET_LOG(status == napi_ok, false, "failed to set property");
561 
562     return true;
563 }
564 
CreateFormatBuffer(napi_env env,Format & format)565 napi_value CommonNapi::CreateFormatBuffer(napi_env env, Format &format)
566 {
567     napi_value buffer = nullptr;
568     int32_t intValue = 0;
569     std::string strValue;
570     napi_status status = napi_create_object(env, &buffer);
571     CHECK_AND_RETURN_RET(status == napi_ok, nullptr);
572 
573     for (auto &iter : format.GetFormatMap()) {
574         switch (format.GetValueType(std::string_view(iter.first))) {
575             case FORMAT_TYPE_INT32:
576                 if (format.GetIntValue(iter.first, intValue)) {
577                     CHECK_AND_RETURN_RET(SetPropertyInt32(env, buffer, iter.first, intValue) == true, nullptr);
578                 }
579                 break;
580             case FORMAT_TYPE_INT64:
581                 int64_t longValue;
582                 if (format.GetLongValue(iter.first, longValue) &&
583                     longValue >= INT32_MIN && longValue <= INT32_MAX) {
584                     intValue = static_cast<int32_t>(longValue);
585                     CHECK_AND_RETURN_RET(SetPropertyInt32(env, buffer, iter.first, intValue) == true, nullptr);
586                 }
587                 break;
588             case FORMAT_TYPE_DOUBLE:
589                 double doubleValue;
590                 if (format.GetDoubleValue(iter.first, doubleValue) &&
591                     doubleValue >= INT32_MIN && doubleValue <= INT32_MAX) {
592                     intValue = static_cast<int32_t>(doubleValue);
593                     CHECK_AND_RETURN_RET(SetPropertyInt32(env, buffer, iter.first, intValue) == true, nullptr);
594                 }
595                 break;
596             case FORMAT_TYPE_STRING:
597                 if (format.GetStringValue(iter.first, strValue)) {
598                     CHECK_AND_RETURN_RET(SetPropertyString(env, buffer, iter.first, strValue) == true, nullptr);
599                 }
600                 break;
601             default:
602                 MEDIA_LOGE("format key: %{public}s", iter.first.c_str());
603                 break;
604         }
605     }
606 
607     return buffer;
608 }
609 
CreateFormatBufferByRef(napi_env env,Format & format,napi_value & result)610 bool CommonNapi::CreateFormatBufferByRef(napi_env env, Format &format, napi_value &result)
611 {
612     int32_t intValue = 0;
613     int64_t longValue = 0;
614     std::string strValue = "";
615     napi_status status = napi_create_object(env, &result);
616     CHECK_AND_RETURN_RET(status == napi_ok, false);
617 
618     for (auto &iter : format.GetFormatMap()) {
619         switch (format.GetValueType(std::string_view(iter.first))) {
620             case FORMAT_TYPE_INT32:
621                 if (format.GetIntValue(iter.first, intValue)) {
622                     (void)SetPropertyInt32(env, result, iter.first, intValue);
623                 }
624                 break;
625             case FORMAT_TYPE_INT64:
626                 if (format.GetLongValue(iter.first, longValue)) {
627                     (void)SetPropertyInt64(env, result, iter.first, longValue);
628                 }
629                 break;
630             case FORMAT_TYPE_STRING:
631                 if (format.GetStringValue(iter.first, strValue)) {
632                     (void)SetPropertyString(env, result, iter.first, strValue);
633                 }
634                 break;
635             default:
636                 MEDIA_LOGE("format key: %{public}s", iter.first.c_str());
637                 break;
638         }
639     }
640 
641     return true;
642 }
643 
AddNumberPropInt32(napi_env env,napi_value obj,const std::string & key,int32_t value)644 bool CommonNapi::AddNumberPropInt32(napi_env env, napi_value obj, const std::string &key, int32_t value)
645 {
646     CHECK_AND_RETURN_RET(obj != nullptr, false);
647 
648     napi_value keyNapi = nullptr;
649     napi_status status = napi_create_string_utf8(env, key.c_str(), NAPI_AUTO_LENGTH, &keyNapi);
650     CHECK_AND_RETURN_RET(status == napi_ok, false);
651 
652     napi_value valueNapi = nullptr;
653     status = napi_create_int32(env, value, &valueNapi);
654     CHECK_AND_RETURN_RET(status == napi_ok, false);
655 
656     status = napi_set_property(env, obj, keyNapi, valueNapi);
657     CHECK_AND_RETURN_RET_LOG(status == napi_ok, false, "Failed to set property");
658 
659     return true;
660 }
661 
AddNumberPropInt64(napi_env env,napi_value obj,const std::string & key,int64_t value)662 bool CommonNapi::AddNumberPropInt64(napi_env env, napi_value obj, const std::string &key, int64_t value)
663 {
664     CHECK_AND_RETURN_RET(obj != nullptr, false);
665 
666     napi_value keyNapi = nullptr;
667     napi_status status = napi_create_string_utf8(env, key.c_str(), NAPI_AUTO_LENGTH, &keyNapi);
668     CHECK_AND_RETURN_RET(status == napi_ok, false);
669 
670     napi_value valueNapi = nullptr;
671     status = napi_create_int64(env, value, &valueNapi);
672     CHECK_AND_RETURN_RET(status == napi_ok, false);
673 
674     status = napi_set_property(env, obj, keyNapi, valueNapi);
675     CHECK_AND_RETURN_RET_LOG(status == napi_ok, false, "Failed to set property");
676 
677     return true;
678 }
679 
GetJsResult(napi_env env,napi_value & result)680 napi_status MediaJsResultStringVector::GetJsResult(napi_env env, napi_value &result)
681 {
682     napi_status status;
683     size_t size = value_.size();
684     napi_create_array_with_length(env, size, &result);
685     for (unsigned int i = 0; i < size; ++i) {
686         std::string format = value_[i];
687         napi_value value = nullptr;
688         status = napi_create_string_utf8(env, format.c_str(), NAPI_AUTO_LENGTH, &value);
689         CHECK_AND_RETURN_RET_LOG(status == napi_ok, status,
690             "Failed to call napi_create_string_utf8, with element %{public}u", i);
691         status = napi_set_element(env, result, i, value);
692         CHECK_AND_RETURN_RET_LOG(status == napi_ok, status,
693             "Failed to call napi_set_element, with element %{public}u", i);
694     }
695     return napi_ok;
696 }
697 
GetJsResult(napi_env env,napi_value & result)698 napi_status MediaJsResultIntArray::GetJsResult(napi_env env, napi_value &result)
699 {
700     napi_status status;
701     size_t size = value_.size();
702     napi_create_array_with_length(env, size, &result);
703     for (unsigned int i = 0; i < size; ++i) {
704         int32_t index = value_[i];
705         napi_value value = nullptr;
706         status = napi_create_int32(env, index, &value);
707         CHECK_AND_RETURN_RET_LOG(status == napi_ok, status,
708             "Failed to call napi_create_int32, with element %{public}u", i);
709         status = napi_set_element(env, result, i, value);
710         CHECK_AND_RETURN_RET_LOG(status == napi_ok, status,
711             "Failed to call napi_set_element, with element %{public}u", i);
712     }
713     return napi_ok;
714 }
715 
GetJsResult(napi_env env,napi_value & result)716 napi_status MediaJsResultArray::GetJsResult(napi_env env, napi_value &result)
717 {
718     // create Description
719     napi_status status = napi_create_array(env, &result);
720     if (status != napi_ok) {
721         return napi_cancelled;
722     }
723 
724     auto vecSize = value_.size();
725     for (size_t index = 0; index < vecSize; ++index) {
726         napi_value description = nullptr;
727         description = CommonNapi::CreateFormatBuffer(env, value_[index]);
728         if (description == nullptr || napi_set_element(env, result, index, description) != napi_ok) {
729             return napi_cancelled;
730         }
731     }
732     return napi_ok;
733 }
734 
MediaAsyncContext(napi_env env)735 MediaAsyncContext::MediaAsyncContext(napi_env env)
736     : env_(env)
737 {
738     MEDIA_LOGD("MediaAsyncContext Create 0x%{public}06" PRIXPTR "", FAKE_POINTER(this));
739 }
740 
~MediaAsyncContext()741 MediaAsyncContext::~MediaAsyncContext()
742 {
743     MEDIA_LOGD("MediaAsyncContext Destroy 0x%{public}06" PRIXPTR "", FAKE_POINTER(this));
744 }
745 
SignError(int32_t code,const std::string & message,bool del)746 void MediaAsyncContext::SignError(int32_t code, const std::string &message, bool del)
747 {
748     errMessage = message;
749     errCode = code;
750     errFlag = true;
751     delFlag = del;
752     MEDIA_LOGE("SignError: %{public}s", message.c_str());
753 }
754 
CompleteCallback(napi_env env,napi_status status,void * data)755 void MediaAsyncContext::CompleteCallback(napi_env env, napi_status status, void *data)
756 {
757     MEDIA_LOGD("CompleteCallback In");
758     auto asyncContext = reinterpret_cast<MediaAsyncContext *>(data);
759     CHECK_AND_RETURN_LOG(asyncContext != nullptr, "asyncContext is nullptr!");
760 
761     std::string memoryTag = asyncContext->memoryTagHead + asyncContext->memoryTagTail;
762     MEDIA_LOGD("MediaAsyncContext Create 0x%{public}06" PRIXPTR " memoryTag = %{public}s",
763         FAKE_POINTER(data), memoryTag.c_str());
764 
765     if (status != napi_ok) {
766         asyncContext->SignError(MSERR_EXT_UNKNOWN, "napi_create_async_work status != napi_ok");
767     }
768 
769     napi_value result = nullptr;
770     napi_get_undefined(env, &result);
771     napi_value args[2] = { nullptr };
772     napi_get_undefined(env, &args[0]);
773     napi_get_undefined(env, &args[1]);
774     if (asyncContext->errFlag) {
775         MEDIA_LOGD("async callback failed");
776         (void)CommonNapi::CreateError(env, asyncContext->errCode, asyncContext->errMessage, result);
777         args[0] = result;
778     } else {
779         MEDIA_LOGD("async callback success");
780         if (asyncContext->JsResult != nullptr) {
781             asyncContext->JsResult->GetJsResult(env, result);
782             CheckCtorResult(env, result, asyncContext, args[0]);
783         }
784         if (!asyncContext->errFlag) {
785             args[1] = result;
786         }
787     }
788 
789     Callback(env, asyncContext, args);
790     napi_delete_async_work(env, asyncContext->work);
791 
792     if (asyncContext->delFlag) {
793         delete asyncContext;
794         asyncContext = nullptr;
795     }
796 }
797 
Callback(napi_env env,const MediaAsyncContext * context,const napi_value * args)798 void MediaAsyncContext::Callback(napi_env env, const MediaAsyncContext *context, const napi_value *args)
799 {
800     if (context->deferred) {
801         if (context->errFlag) {
802             MEDIA_LOGE("promise napi_reject_deferred");
803             napi_reject_deferred(env, context->deferred, args[0]);
804         } else {
805             MEDIA_LOGD("promise napi_resolve_deferred");
806             napi_resolve_deferred(env, context->deferred, args[1]);
807         }
808     } else if (context->callbackRef != nullptr) {
809         MEDIA_LOGD("callback napi_call_function");
810         napi_value callback = nullptr;
811         napi_get_reference_value(env, context->callbackRef, &callback);
812         CHECK_AND_RETURN_LOG(callback != nullptr, "callback is nullptr!");
813         constexpr size_t argCount = 2;
814         napi_value retVal;
815         napi_get_undefined(env, &retVal);
816         napi_call_function(env, nullptr, callback, argCount, args, &retVal);
817         napi_delete_reference(env, context->callbackRef);
818     } else {
819         MEDIA_LOGE("invalid promise and callback");
820     }
821 }
822 
CheckCtorResult(napi_env env,napi_value & result,MediaAsyncContext * ctx,napi_value & args)823 void MediaAsyncContext::CheckCtorResult(napi_env env, napi_value &result, MediaAsyncContext *ctx, napi_value &args)
824 {
825     CHECK_AND_RETURN(ctx != nullptr);
826     if (ctx->ctorFlag) {
827         void *instance = nullptr;
828         if (napi_unwrap(env, result, reinterpret_cast<void **>(&instance)) != napi_ok || instance == nullptr) {
829             MEDIA_LOGE("Failed to create instance");
830             ctx->errFlag = true;
831             (void)CommonNapi::CreateError(env, MSERR_EXT_API9_NO_MEMORY,
832                 "The instance or memory has reached the upper limit, please recycle background playback", result);
833             args = result;
834         }
835     }
836 }
837 
AddStringProperty(napi_env env,napi_value obj,const std::string & key,const std::string & value)838 bool CommonNapi::AddStringProperty(napi_env env, napi_value obj, const std::string &key, const std::string &value)
839 {
840     CHECK_AND_RETURN_RET(obj != nullptr, false);
841 
842     napi_value keyNapi = nullptr;
843     napi_status status = napi_create_string_utf8(env, key.c_str(), NAPI_AUTO_LENGTH, &keyNapi);
844     CHECK_AND_RETURN_RET(status == napi_ok, false);
845 
846     napi_value valueNapi = nullptr;
847     status = napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &valueNapi);
848     CHECK_AND_RETURN_RET(status == napi_ok, false);
849 
850     status = napi_set_property(env, obj, keyNapi, valueNapi);
851     CHECK_AND_RETURN_RET_LOG(status == napi_ok, false, "Failed to set property");
852 
853     return true;
854 }
855 
GetPropertyBool(napi_env env,napi_value configObj,const std::string & type,bool & result)856 bool CommonNapi::GetPropertyBool(napi_env env, napi_value configObj, const std::string &type, bool &result)
857 {
858     bool exist = false;
859     napi_status status = napi_has_named_property(env, configObj, type.c_str(), &exist);
860     if (status != napi_ok || !exist) {
861         MEDIA_LOGE("can not find %{public}s property", type.c_str());
862         return false;
863     }
864     napi_value item = nullptr;
865     if (napi_get_named_property(env, configObj, type.c_str(), &item) != napi_ok) {
866         MEDIA_LOGE("get %{public}s property fail", type.c_str());
867         return false;
868     }
869     if (napi_get_value_bool(env, item, &result) != napi_ok) {
870         MEDIA_LOGE("get %{public}s property value fail", type.c_str());
871         return false;
872     }
873     return true;
874 }
875 
ConvertDeviceInfoToAudioDeviceDescriptor(sptr<AudioStandard::AudioDeviceDescriptor> audioDeviceDescriptor,const AudioStandard::DeviceInfo & deviceInfo)876 void CommonNapi::ConvertDeviceInfoToAudioDeviceDescriptor(
877     sptr<AudioStandard::AudioDeviceDescriptor> audioDeviceDescriptor, const AudioStandard::DeviceInfo &deviceInfo)
878 {
879     CHECK_AND_RETURN_LOG(audioDeviceDescriptor != nullptr, "audioDeviceDescriptor is nullptr");
880     audioDeviceDescriptor->deviceRole_ = deviceInfo.deviceRole;
881     audioDeviceDescriptor->deviceType_ = deviceInfo.deviceType;
882     audioDeviceDescriptor->deviceId_ = deviceInfo.deviceId;
883     audioDeviceDescriptor->channelMasks_ = deviceInfo.channelMasks;
884     audioDeviceDescriptor->channelIndexMasks_ = deviceInfo.channelIndexMasks;
885     audioDeviceDescriptor->deviceName_ = deviceInfo.deviceName;
886     audioDeviceDescriptor->macAddress_ = deviceInfo.macAddress;
887     audioDeviceDescriptor->interruptGroupId_ = deviceInfo.interruptGroupId;
888     audioDeviceDescriptor->volumeGroupId_ = deviceInfo.volumeGroupId;
889     audioDeviceDescriptor->networkId_ = deviceInfo.networkId;
890     audioDeviceDescriptor->displayName_ = deviceInfo.displayName;
891     audioDeviceDescriptor->audioStreamInfo_.samplingRate = deviceInfo.audioStreamInfo.samplingRate;
892     audioDeviceDescriptor->audioStreamInfo_.encoding = deviceInfo.audioStreamInfo.encoding;
893     audioDeviceDescriptor->audioStreamInfo_.format = deviceInfo.audioStreamInfo.format;
894     audioDeviceDescriptor->audioStreamInfo_.channels = deviceInfo.audioStreamInfo.channels;
895 }
896 
SetDeviceDescriptor(const napi_env & env,const AudioStandard::AudioDeviceDescriptor & deviceInfo,napi_value & result)897 napi_status CommonNapi::SetDeviceDescriptor(const napi_env &env, const AudioStandard::AudioDeviceDescriptor &deviceInfo,
898     napi_value &result)
899 {
900     (void)napi_create_object(env, &result);
901     SetPropertyInt32(env, result, "deviceRole", static_cast<int32_t>(deviceInfo.deviceRole_));
902     SetPropertyInt32(env, result, "deviceType", static_cast<int32_t>(deviceInfo.deviceType_));
903     SetPropertyInt32(env, result, "id", static_cast<int32_t>(deviceInfo.deviceId_));
904     SetPropertyString(env, result, "name", deviceInfo.deviceName_);
905     SetPropertyString(env, result, "address", deviceInfo.macAddress_);
906     SetPropertyString(env, result, "networkId", deviceInfo.networkId_);
907     SetPropertyString(env, result, "displayName", deviceInfo.displayName_);
908     SetPropertyInt32(env, result, "interruptGroupId", static_cast<int32_t>(deviceInfo.interruptGroupId_));
909     SetPropertyInt32(env, result, "volumeGroupId", static_cast<int32_t>(deviceInfo.volumeGroupId_));
910 
911     napi_value value = nullptr;
912     napi_value sampleRates;
913     size_t size = deviceInfo.audioStreamInfo_.samplingRate.size();
914     napi_create_array_with_length(env, size, &sampleRates);
915     size_t count = 0;
916     for (const auto &samplingRate : deviceInfo.audioStreamInfo_.samplingRate) {
917         napi_create_int32(env, samplingRate, &value);
918         napi_set_element(env, sampleRates, count, value);
919         count++;
920     }
921     napi_set_named_property(env, result, "sampleRates", sampleRates);
922 
923     napi_value channelCounts;
924     size = deviceInfo.audioStreamInfo_.channels.size();
925     napi_create_array_with_length(env, size, &channelCounts);
926     count = 0;
927     for (const auto &channels : deviceInfo.audioStreamInfo_.channels) {
928         napi_create_int32(env, channels, &value);
929         napi_set_element(env, channelCounts, count, value);
930         count++;
931     }
932     napi_set_named_property(env, result, "channelCounts", channelCounts);
933 
934     std::vector<int32_t> channelMasks_;
935     channelMasks_.push_back(deviceInfo.channelMasks_);
936     AddArrayProperty(env, result, "channelMasks", channelMasks_);
937 
938     std::vector<int32_t> channelIndexMasks_;
939     channelIndexMasks_.push_back(deviceInfo.channelIndexMasks_);
940     AddArrayProperty(env, result, "channelIndexMasks", channelIndexMasks_);
941 
942     std::vector<int32_t> encoding;
943     encoding.push_back(deviceInfo.audioStreamInfo_.encoding);
944     AddArrayProperty(env, result, "encodingTypes", encoding);
945 
946     return napi_ok;
947 }
948 
SetDeviceDescriptors(const napi_env & env,const std::vector<sptr<AudioStandard::AudioDeviceDescriptor>> & deviceDescriptors,napi_value & result)949 napi_status CommonNapi::SetDeviceDescriptors(const napi_env &env,
950     const std::vector<sptr<AudioStandard::AudioDeviceDescriptor>> &deviceDescriptors, napi_value &result)
951 {
952     napi_status status = napi_create_array_with_length(env, deviceDescriptors.size(), &result);
953     for (size_t i = 0; i < deviceDescriptors.size(); i++) {
954         if (deviceDescriptors[i] != nullptr) {
955             napi_value valueParam = nullptr;
956             SetDeviceDescriptor(env, deviceDescriptors[i], valueParam);
957             napi_set_element(env, result, i, valueParam);
958         }
959     }
960     return status;
961 }
962 
SetValueDeviceInfo(const napi_env & env,const AudioStandard::DeviceInfo & deviceInfo,napi_value & result)963 napi_status CommonNapi::SetValueDeviceInfo(const napi_env &env, const AudioStandard::DeviceInfo &deviceInfo,
964     napi_value &result)
965 {
966     std::vector<sptr<AudioStandard::AudioDeviceDescriptor>> deviceDescriptors;
967     sptr<AudioStandard::AudioDeviceDescriptor> audioDeviceDescriptor =
968         new(std::nothrow) AudioStandard::AudioDeviceDescriptor();
969     CHECK_AND_RETURN_RET_LOG(audioDeviceDescriptor != nullptr, napi_generic_failure,
970         "audioDeviceDescriptor malloc failed");
971     ConvertDeviceInfoToAudioDeviceDescriptor(audioDeviceDescriptor, deviceInfo);
972     deviceDescriptors.push_back(std::move(audioDeviceDescriptor));
973     SetDeviceDescriptors(env, deviceDescriptors, result);
974     return napi_ok;
975 }
976 } // namespace Media
977 } // namespace OHOS