1 /*
2  * Copyright (C) 2021-2022 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 "napi_ashmem.h"
17 #include <cinttypes>
18 #include <limits>
19 #include <unistd.h>
20 #include "ipc_debug.h"
21 #include "log_tags.h"
22 #include "securec.h"
23 #include "napi_rpc_error.h"
24 
25 namespace OHOS {
26 static constexpr OHOS::HiviewDFX::HiLogLabel LOG_LABEL = { LOG_CORE, LOG_ID_IPC_NAPI, "napi_ashmem" };
27 
28 static constexpr int MMAP_PROT_MAX = NAPIAshmem::PROT_EXEC | NAPIAshmem::PROT_READ | NAPIAshmem::PROT_WRITE;
29 constexpr size_t BYTE_SIZE_32 = 4;
30 
31 NapiError NAPIAshmem::napiErr;
32 
33 static const size_t ARGV_INDEX_0 = 0;
34 static const size_t ARGV_INDEX_1 = 1;
35 static const size_t ARGV_INDEX_2 = 2;
36 
37 static const size_t ARGV_LENGTH_1 = 1;
38 static const size_t ARGV_LENGTH_2 = 2;
39 static const size_t ARGV_LENGTH_3 = 3;
NAPIAshmem(sptr<Ashmem> & ashmem)40 NAPIAshmem::NAPIAshmem(sptr<Ashmem> &ashmem) : ashmem_(ashmem)
41 {
42     if (ashmem == nullptr) {
43         ZLOGE(LOG_LABEL, "ashmem is null");
44     }
45 }
46 
CloseAshmem(napi_env env,napi_callback_info info)47 napi_value NAPIAshmem::CloseAshmem(napi_env env, napi_callback_info info)
48 {
49     napi_value thisVar = nullptr;
50     napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
51     NAPIAshmem *napiAshmem = nullptr;
52     napi_unwrap(env, thisVar, (void **)&napiAshmem);
53     NAPI_ASSERT(env, napiAshmem != nullptr, "napiAshmem is null");
54     napiAshmem->GetAshmem()->CloseAshmem();
55     napi_value result = nullptr;
56     napi_get_undefined(env, &result);
57     return result;
58 }
59 
CreateAshmem(napi_env env,napi_callback_info info)60 napi_value NAPIAshmem::CreateAshmem(napi_env env, napi_callback_info info)
61 {
62     napi_value thisVar = nullptr;
63     size_t argc = 2;
64     napi_value argv[ARGV_LENGTH_2] = { 0 };
65     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
66     NAPI_ASSERT(env, argc == 2, "requires 2 parameter");
67     napi_valuetype valueType = napi_null;
68     napi_typeof(env, argv[ARGV_INDEX_0], &valueType);
69     if (valueType != napi_string) {
70         ZLOGE(LOG_LABEL, "type mismatch for parameter 1");
71         return nullptr;
72     }
73     size_t bufferSize = 0;
74     napi_get_value_string_utf8(env, argv[ARGV_INDEX_0], nullptr, 0, &bufferSize);
75     if (bufferSize == 0) {
76         ZLOGE(LOG_LABEL, "invalid ashmem name");
77         return nullptr;
78     }
79     napi_typeof(env, argv[ARGV_INDEX_1], &valueType);
80     if (valueType != napi_number) {
81         ZLOGE(LOG_LABEL, "type mismatch for parameter 2");
82         return nullptr;
83     }
84     int32_t ashmemSize = 0;
85     napi_get_value_int32(env, argv[ARGV_INDEX_1], &ashmemSize);
86     if (ashmemSize <= 0) {
87         ZLOGE(LOG_LABEL, "invalid ashmem size");
88         return nullptr;
89     }
90     napi_value global = nullptr;
91     napi_status status = napi_get_global(env, &global);
92     NAPI_ASSERT(env, status == napi_ok, "get napi global failed");
93     napi_value constructor = nullptr;
94     status = napi_get_named_property(env, global, "AshmemConstructor_", &constructor);
95     NAPI_ASSERT(env, status == napi_ok, "get Ashmem constructor failed");
96     napi_value jsAshmem;
97     status = napi_new_instance(env, constructor, 2, argv, &jsAshmem);
98     NAPI_ASSERT(env, status == napi_ok, "failed to  construct js Ashmem");
99     return jsAshmem;
100 }
101 
CreateAshmemFromExisting(napi_env env,napi_callback_info info)102 napi_value NAPIAshmem::CreateAshmemFromExisting(napi_env env, napi_callback_info info)
103 {
104     size_t argc = 1;
105     napi_value argv[ARGV_LENGTH_1] = {nullptr};
106     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
107     NAPI_ASSERT(env, argc == 1, "requires 1 parameter");
108     napi_value global = nullptr;
109     napi_status status = napi_get_global(env, &global);
110     NAPI_ASSERT(env, status == napi_ok, "get napi global failed");
111     napi_value constructor = nullptr;
112     status = napi_get_named_property(env, global, "AshmemConstructor_", &constructor);
113     NAPI_ASSERT(env, status == napi_ok, "get Ashmem constructor failed");
114     bool isAshmem = false;
115     napi_instanceof(env, argv[ARGV_INDEX_0], constructor, &isAshmem);
116     NAPI_ASSERT(env, isAshmem == true, "parameter is not instanceof Ashmem");
117     NAPIAshmem *napiAshmem = nullptr;
118     napi_unwrap(env, argv[ARGV_INDEX_0], (void **)&napiAshmem);
119     NAPI_ASSERT(env, napiAshmem != nullptr, "napiAshmem is null");
120     int32_t fd = napiAshmem->GetAshmem()->GetAshmemFd();
121     uint32_t size = (uint32_t)(napiAshmem->GetAshmem()->GetAshmemSize());
122     NAPI_ASSERT(env,  (fd > 0) && (size > 0), "fd <= 0 or  size <= 0");
123     sptr<Ashmem> newAshmem(new Ashmem(dup(fd), size));
124     NAPI_ASSERT(env, newAshmem != nullptr, "napiAshmem is null");
125     napi_value jsAshmem = nullptr;
126     status = napi_new_instance(env, constructor, 0, nullptr, &jsAshmem);
127     NAPI_ASSERT(env, status == napi_ok, "failed to  construct js Ashmem");
128     NAPIAshmem *newNapiAshmem = nullptr;
129     napi_unwrap(env, jsAshmem, (void **)&newNapiAshmem);
130     NAPI_ASSERT(env, newNapiAshmem != nullptr, "newNapiAshmem is null");
131     newNapiAshmem->SetAshmem(newAshmem);
132     return jsAshmem;
133 }
134 
Create(napi_env env,napi_callback_info info)135 napi_value NAPIAshmem::Create(napi_env env, napi_callback_info info)
136 {
137     napi_value thisVar = nullptr;
138     size_t argc = 2;
139     size_t argcExistingAshmem = 1;
140     size_t argcAshmem = 2;
141     napi_value argv[ARGV_LENGTH_2] = { 0 };
142     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
143     if ((argc != argcExistingAshmem) && (argc != argcAshmem)) {
144         ZLOGE(LOG_LABEL, "requires 1 or 2 parameter");
145         return napiErr.ThrowError(env, OHOS::errorDesc::CHECK_PARAM_ERROR);
146     }
147 
148     if (argc == argcExistingAshmem) {
149         return GetAshmemFromExisting(env, info);
150     }
151 
152     napi_valuetype valueType = napi_null;
153     napi_typeof(env, argv[ARGV_INDEX_0], &valueType);
154     if (valueType != napi_string) {
155         ZLOGE(LOG_LABEL, "type mismatch for parameter 1");
156         return napiErr.ThrowError(env, OHOS::errorDesc::CHECK_PARAM_ERROR);
157     }
158     size_t bufferSize = 0;
159     napi_get_value_string_utf8(env, argv[ARGV_INDEX_0], nullptr, 0, &bufferSize);
160     if (bufferSize == 0) {
161         ZLOGE(LOG_LABEL, "invalid ashmem name");
162         return napiErr.ThrowError(env, OHOS::errorDesc::CHECK_PARAM_ERROR);
163     }
164 
165     napi_typeof(env, argv[ARGV_INDEX_1], &valueType);
166     if (valueType != napi_number) {
167         ZLOGE(LOG_LABEL, "type mismatch for parameter 2");
168         return napiErr.ThrowError(env, OHOS::errorDesc::CHECK_PARAM_ERROR);
169     }
170 
171     int32_t ashmemSize = 0;
172     napi_get_value_int32(env, argv[ARGV_INDEX_1], &ashmemSize);
173     if (ashmemSize <= 0) {
174         ZLOGE(LOG_LABEL, "invalid ashmem size");
175         return napiErr.ThrowError(env, OHOS::errorDesc::CHECK_PARAM_ERROR);
176     }
177 
178     return GetAshmemConstructor(env, argv);
179 }
180 
GetAshmemConstructor(napi_env env,napi_value * argv)181 napi_value NAPIAshmem::GetAshmemConstructor(napi_env env, napi_value* argv)
182 {
183     napi_value global = nullptr;
184     napi_status status = napi_get_global(env, &global);
185     if (status != napi_ok) {
186         ZLOGE(LOG_LABEL, "get napi global failed");
187         return nullptr;
188     }
189     napi_value constructor = nullptr;
190     status = napi_get_named_property(env, global, "AshmemConstructor_", &constructor);
191     if (status != napi_ok) {
192         ZLOGE(LOG_LABEL, "get Ashmem constructor failed");
193         return nullptr;
194     }
195     napi_value jsAshmem;
196     status = napi_new_instance(env, constructor, 2, argv, &jsAshmem);
197     if (status != napi_ok) {
198         ZLOGE(LOG_LABEL, "failed to  construct js Ashmem");
199         return nullptr;
200     }
201     return jsAshmem;
202 }
203 
GetAshmemFromExisting(napi_env env,napi_callback_info info)204 napi_value NAPIAshmem::GetAshmemFromExisting(napi_env env, napi_callback_info info)
205 {
206     size_t argc = 1;
207     napi_value argv[ARGV_LENGTH_1] = {nullptr};
208     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
209     napi_value global = nullptr;
210     napi_status status = napi_get_global(env, &global);
211     if (status != napi_ok) {
212         ZLOGE(LOG_LABEL, "get napi global failed");
213         return nullptr;
214     }
215     napi_value constructor = nullptr;
216     status = napi_get_named_property(env, global, "AshmemConstructor_", &constructor);
217     if (status != napi_ok) {
218         ZLOGE(LOG_LABEL, "get Ashmem constructor failed");
219         return nullptr;
220     }
221     bool isAshmem = false;
222     napi_instanceof(env, argv[ARGV_INDEX_0], constructor, &isAshmem);
223     if (isAshmem == false) {
224         ZLOGE(LOG_LABEL, "parameter is not instanceof Ashmem");
225         return napiErr.ThrowError(env, OHOS::errorDesc::CHECK_PARAM_ERROR);
226     }
227     NAPIAshmem *napiAshmem = nullptr;
228     napi_unwrap(env, argv[ARGV_INDEX_0], (void **)&napiAshmem);
229     if (napiAshmem == nullptr) {
230         ZLOGE(LOG_LABEL, "napiAshmem is null");
231         return napiErr.ThrowError(env, OHOS::errorDesc::CHECK_PARAM_ERROR);
232     }
233     int32_t fd = napiAshmem->GetAshmem()->GetAshmemFd();
234     uint32_t size = (uint32_t)(napiAshmem->GetAshmem()->GetAshmemSize());
235     if (fd <= 0 || size <= 0) {
236         ZLOGE(LOG_LABEL, "fd <= 0 or  size <= 0");
237         return nullptr;
238     }
239 
240     return getNewAshmemConstructor(env, constructor, fd, size);
241 }
242 
getNewAshmemConstructor(napi_env env,napi_value & constructor,int32_t fd,uint32_t size)243 napi_value NAPIAshmem::getNewAshmemConstructor(napi_env env, napi_value& constructor, int32_t fd, uint32_t size)
244 {
245     sptr<Ashmem> newAshmem(new Ashmem(dup(fd), size));
246     if (newAshmem == nullptr) {
247         ZLOGE(LOG_LABEL, "newAshmem is null");
248         return napiErr.ThrowError(env, OHOS::errorDesc::CHECK_PARAM_ERROR);
249     }
250 
251     napi_value jsAshmem = nullptr;
252     napi_status status = napi_new_instance(env, constructor, 0, nullptr, &jsAshmem);
253     if (status != napi_ok) {
254         ZLOGE(LOG_LABEL, "failed to  construct js Ashmem");
255         return nullptr;
256     }
257     NAPIAshmem *newNapiAshmem = nullptr;
258     napi_unwrap(env, jsAshmem, (void **)&newNapiAshmem);
259     if (newNapiAshmem == nullptr) {
260         ZLOGE(LOG_LABEL, "newNapiAshmem is null");
261         return nullptr;
262     }
263     newNapiAshmem->SetAshmem(newAshmem);
264     return jsAshmem;
265 }
266 
GetAshmemSize(napi_env env,napi_callback_info info)267 napi_value NAPIAshmem::GetAshmemSize(napi_env env, napi_callback_info info)
268 {
269     napi_value thisVar = nullptr;
270     napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
271     NAPIAshmem *napiAshmem = nullptr;
272     napi_unwrap(env, thisVar, (void **)&napiAshmem);
273     NAPI_ASSERT(env, napiAshmem != nullptr, "napiAshmem is null");
274     uint32_t ashmemSize = (uint32_t)(napiAshmem->GetAshmem()->GetAshmemSize());
275     napi_value napiValue;
276     napi_create_uint32(env, ashmemSize, &napiValue);
277     return napiValue;
278 }
279 
MapAshmem(napi_env env,napi_callback_info info)280 napi_value NAPIAshmem::MapAshmem(napi_env env, napi_callback_info info)
281 {
282     napi_value thisVar = nullptr;
283     size_t argc = 1;
284     napi_value argv[ARGV_LENGTH_1] = {0};
285     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
286     NAPI_ASSERT(env, argc == 1, "requires 1 parameter");
287     napi_valuetype valueType = napi_null;
288     napi_typeof(env, argv[ARGV_INDEX_0], &valueType);
289     NAPI_ASSERT(env, valueType == napi_number, "type mismatch for parameter 1");
290     uint32_t mapType = 0;
291     napi_get_value_uint32(env, argv[ARGV_INDEX_0], &mapType);
292     NAPI_ASSERT(env, mapType <= MMAP_PROT_MAX, "napiAshmem mapType error");
293     NAPIAshmem *napiAshmem = nullptr;
294     napi_unwrap(env, thisVar, (void **)&napiAshmem);
295     NAPI_ASSERT(env, napiAshmem != nullptr, "napiAshmem is null");
296     bool result = napiAshmem->GetAshmem()->MapAshmem(mapType);
297     napi_value napiValue = nullptr;
298     NAPI_CALL(env, napi_get_boolean(env, result, &napiValue));
299     return napiValue;
300 }
301 
MapTypedAshmem(napi_env env,napi_callback_info info)302 napi_value NAPIAshmem::MapTypedAshmem(napi_env env, napi_callback_info info)
303 {
304     napi_value thisVar = nullptr;
305     size_t argc = 1;
306     napi_value argv[ARGV_LENGTH_1] = {0};
307     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
308     if (argc != 1) {
309         ZLOGE(LOG_LABEL, "requires 1 parameter");
310         return napiErr.ThrowError(env, OHOS::errorDesc::CHECK_PARAM_ERROR);
311     }
312     napi_valuetype valueType = napi_null;
313     napi_typeof(env, argv[ARGV_INDEX_0], &valueType);
314     if (valueType != napi_number) {
315         ZLOGE(LOG_LABEL, "type mismatch for parameter 1");
316         return napiErr.ThrowError(env, OHOS::errorDesc::CHECK_PARAM_ERROR);
317     }
318     uint32_t mapType = 0;
319     napi_get_value_uint32(env, argv[ARGV_INDEX_0], &mapType);
320     if (mapType > MMAP_PROT_MAX) {
321         ZLOGE(LOG_LABEL, "napiAshmem mapType error");
322         return napiErr.ThrowError(env, OHOS::errorDesc::CHECK_PARAM_ERROR);
323     }
324     NAPIAshmem *napiAshmem = nullptr;
325     napi_unwrap(env, thisVar, (void **)&napiAshmem);
326     if (napiAshmem == nullptr) {
327         ZLOGE(LOG_LABEL, "napiAshmem is null");
328         return napiErr.ThrowError(env, OHOS::errorDesc::OS_MMAP_ERROR);
329     }
330     napiAshmem->GetAshmem()->MapAshmem(mapType);
331     napi_value result = nullptr;
332     napi_get_undefined(env, &result);
333     return result;
334 }
335 
MapReadAndWriteAshmem(napi_env env,napi_callback_info info)336 napi_value NAPIAshmem::MapReadAndWriteAshmem(napi_env env, napi_callback_info info)
337 {
338     napi_value thisVar = nullptr;
339     napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
340     NAPIAshmem *napiAshmem = nullptr;
341     napi_unwrap(env, thisVar, (void **)&napiAshmem);
342     NAPI_ASSERT(env, napiAshmem != nullptr, "napiAshmem is null");
343     bool result = napiAshmem->GetAshmem()->MapReadAndWriteAshmem();
344     napi_value napiValue = nullptr;
345     NAPI_CALL(env, napi_get_boolean(env, result, &napiValue));
346     return napiValue;
347 }
348 
MapReadWriteAshmem(napi_env env,napi_callback_info info)349 napi_value NAPIAshmem::MapReadWriteAshmem(napi_env env, napi_callback_info info)
350 {
351     napi_value thisVar = nullptr;
352     napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
353     NAPIAshmem *napiAshmem = nullptr;
354     napi_unwrap(env, thisVar, (void **)&napiAshmem);
355     if (napiAshmem == nullptr) {
356         ZLOGE(LOG_LABEL, "napiAshmem is null");
357         return napiErr.ThrowError(env, OHOS::errorDesc::OS_MMAP_ERROR);
358     }
359     napiAshmem->GetAshmem()->MapReadAndWriteAshmem();
360     napi_value result = nullptr;
361     napi_get_undefined(env, &result);
362     return result;
363 }
364 
MapReadOnlyAshmem(napi_env env,napi_callback_info info)365 napi_value NAPIAshmem::MapReadOnlyAshmem(napi_env env, napi_callback_info info)
366 {
367     napi_value thisVar = nullptr;
368     napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
369     NAPIAshmem *napiAshmem = nullptr;
370     napi_unwrap(env, thisVar, (void **)&napiAshmem);
371     NAPI_ASSERT(env, napiAshmem != nullptr, "napiAshmem is null");
372     bool result = napiAshmem->GetAshmem()->MapReadOnlyAshmem();
373     napi_value napiValue = nullptr;
374     NAPI_CALL(env, napi_get_boolean(env, result, &napiValue));
375     return napiValue;
376 }
377 
MapReadonlyAshmem(napi_env env,napi_callback_info info)378 napi_value NAPIAshmem::MapReadonlyAshmem(napi_env env, napi_callback_info info)
379 {
380     napi_value thisVar = nullptr;
381     napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
382     NAPIAshmem *napiAshmem = nullptr;
383     napi_unwrap(env, thisVar, (void **)&napiAshmem);
384     if (napiAshmem == nullptr) {
385         ZLOGE(LOG_LABEL, "napiAshmem is null");
386         return napiErr.ThrowError(env, OHOS::errorDesc::OS_MMAP_ERROR);
387     }
388     napiAshmem->GetAshmem()->MapReadOnlyAshmem();
389     napi_value result = nullptr;
390     napi_get_undefined(env, &result);
391     return result;
392 }
393 
ReadFromAshmem(napi_env env,napi_callback_info info)394 napi_value NAPIAshmem::ReadFromAshmem(napi_env env, napi_callback_info info)
395 {
396     napi_value thisVar = nullptr;
397     size_t argc = 2;
398     napi_value argv[ARGV_LENGTH_2] = {0};
399     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
400     NAPI_ASSERT(env, argc == 2, "requires 2 parameter");
401     napi_valuetype valueType = napi_null;
402     napi_typeof(env, argv[ARGV_INDEX_0], &valueType);
403     NAPI_ASSERT(env, valueType == napi_number, "type mismatch for parameter 1");
404     napi_typeof(env, argv[ARGV_INDEX_1], &valueType);
405     NAPI_ASSERT(env, valueType == napi_number, "type mismatch for parameter 2");
406     int64_t size = 0;
407     napi_get_value_int64(env, argv[ARGV_INDEX_0], &size);
408     int64_t offset = 0;
409     napi_get_value_int64(env, argv[ARGV_INDEX_1], &offset);
410     NAPIAshmem *napiAshmem = nullptr;
411     napi_unwrap(env, thisVar, (void **)&napiAshmem);
412     NAPI_ASSERT(env, napiAshmem != nullptr, "napiAshmem is null");
413 
414     uint32_t ashmemSize = (uint32_t)napiAshmem->GetAshmem()->GetAshmemSize();
415     if (size < 0 || size > static_cast<int64_t>(std::numeric_limits<int32_t>::max() / BYTE_SIZE_32) ||
416         offset < 0 || offset > static_cast<int64_t>(std::numeric_limits<int32_t>::max() / BYTE_SIZE_32) ||
417         (size * BYTE_SIZE_32 + offset * BYTE_SIZE_32) > ashmemSize) {
418         ZLOGE(LOG_LABEL, "invalid parameter, size:%{public}jd offset:%{public}jd", size, offset);
419         return nullptr;
420     }
421     size *= BYTE_SIZE_32;
422     offset *= BYTE_SIZE_32;
423     const void  *result = napiAshmem->GetAshmem()->ReadFromAshmem(size, offset);
424     if (result == nullptr) {
425         ZLOGE(LOG_LABEL, "ashmem->ReadFromAshmem returns null");
426         return nullptr;
427     }
428     // c++ byte[] to js []
429     napi_value arrayBuffer = nullptr;
430     void *arrayBufferPtr = nullptr;
431     napi_create_arraybuffer(env, size, &arrayBufferPtr, &arrayBuffer);
432     napi_value typedArray = nullptr;
433     napi_create_typedarray(env, napi_int32_array, size / BYTE_SIZE_32, arrayBuffer, 0, &typedArray);
434     bool isTypedArray = false;
435     napi_is_typedarray(env, typedArray, &isTypedArray);
436     NAPI_ASSERT(env, isTypedArray == true, "create  TypedArray failed");
437     if (size == 0) {
438         return typedArray;
439     }
440     errno_t status = memcpy_s(arrayBufferPtr, size, result, size);
441     NAPI_ASSERT(env, status == EOK, "memcpy_s is failed");
442     return typedArray;
443 }
444 
ReadAshmem(napi_env env,napi_callback_info info)445 napi_value NAPIAshmem::ReadAshmem(napi_env env, napi_callback_info info)
446 {
447     napi_value thisVar = nullptr;
448     size_t argc = 2;
449     size_t argNum = 2;
450     napi_value argv[ARGV_LENGTH_2] = {0};
451     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
452     if (argc != argNum) {
453         ZLOGE(LOG_LABEL, "requires 2 parameter");
454         return napiErr.ThrowError(env, OHOS::errorDesc::CHECK_PARAM_ERROR);
455     }
456     napi_valuetype valueType = napi_null;
457     napi_typeof(env, argv[ARGV_INDEX_0], &valueType);
458     if (valueType != napi_number) {
459         ZLOGE(LOG_LABEL, "type mismatch for parameter 1");
460         return napiErr.ThrowError(env, OHOS::errorDesc::CHECK_PARAM_ERROR);
461     }
462     napi_typeof(env, argv[ARGV_INDEX_1], &valueType);
463     if (valueType != napi_number) {
464         ZLOGE(LOG_LABEL, "type mismatch for parameter 2");
465         return napiErr.ThrowError(env, OHOS::errorDesc::CHECK_PARAM_ERROR);
466     }
467     int64_t size = 0;
468     napi_get_value_int64(env, argv[ARGV_INDEX_0], &size);
469     int64_t offset = 0;
470     napi_get_value_int64(env, argv[ARGV_INDEX_1], &offset);
471     NAPIAshmem *napiAshmem = nullptr;
472     napi_unwrap(env, thisVar, (void **)&napiAshmem);
473     if (napiAshmem == nullptr) {
474         ZLOGE(LOG_LABEL, "napiAshmem is null");
475         return napiErr.ThrowError(env, OHOS::errorDesc::READ_FROM_ASHMEM_ERROR);
476     }
477     uint32_t ashmemSize = (uint32_t)napiAshmem->GetAshmem()->GetAshmemSize();
478     if (size < 0 || size > (int64_t)(std::numeric_limits<int32_t>::max() / BYTE_SIZE_32) ||
479         offset < 0 || offset > (int64_t)(std::numeric_limits<int32_t>::max() / BYTE_SIZE_32) ||
480         (size * BYTE_SIZE_32 + offset * BYTE_SIZE_32) > ashmemSize) {
481         ZLOGE(LOG_LABEL, "invalid parameter, size:%{public}jd offset:%{public}jd", size, offset);
482         return nullptr;
483     }
484     size *= BYTE_SIZE_32;
485     offset *= BYTE_SIZE_32;
486     const void  *result = napiAshmem->GetAshmem()->ReadFromAshmem(size, offset);
487     if (result == nullptr) {
488         ZLOGE(LOG_LABEL, "ashmem->ReadFromAshmem returns null");
489         return nullptr;
490     }
491     // c++ byte[] to js []
492     return TransferByteToJsData(env, size, result);
493 }
494 
TransferByteToJsData(napi_env env,uint32_t size,const void * result)495 napi_value NAPIAshmem::TransferByteToJsData(napi_env env, uint32_t size, const void *result)
496 {
497     napi_value arrayBuffer = nullptr;
498     void *arrayBufferPtr = nullptr;
499     napi_create_arraybuffer(env, size, &arrayBufferPtr, &arrayBuffer);
500     napi_value typedArray = nullptr;
501     napi_create_typedarray(env, napi_int32_array, size / BYTE_SIZE_32, arrayBuffer, 0, &typedArray);
502     bool isTypedArray = false;
503     napi_is_typedarray(env, typedArray, &isTypedArray);
504     NAPI_ASSERT(env, isTypedArray == true, "create  TypedArray failed");
505     if (!isTypedArray) {
506         ZLOGE(LOG_LABEL, "napiAshmem is null");
507         return napiErr.ThrowError(env, OHOS::errorDesc::READ_FROM_ASHMEM_ERROR);
508     }
509     if (size == 0) {
510         return typedArray;
511     }
512     errno_t status = memcpy_s(arrayBufferPtr, size, result, size);
513     if (status != EOK) {
514         ZLOGE(LOG_LABEL, "memcpy_s is failed");
515         return napiErr.ThrowError(env, OHOS::errorDesc::READ_FROM_ASHMEM_ERROR);
516     }
517     return typedArray;
518 }
519 
SetProtection(napi_env env,napi_callback_info info)520 napi_value NAPIAshmem::SetProtection(napi_env env, napi_callback_info info)
521 {
522     napi_value thisVar = nullptr;
523     size_t argc = 1;
524     napi_value argv[ARGV_LENGTH_1] = { 0 };
525     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
526     NAPI_ASSERT(env, argc == 1, "requires 1 parameter");
527     napi_valuetype valueType = napi_null;
528     napi_typeof(env, argv[ARGV_INDEX_0], &valueType);
529     NAPI_ASSERT(env, valueType == napi_number, "type mismatch for parameter 1");
530     uint32_t protectionType = 0;
531     napi_get_value_uint32(env, argv[ARGV_INDEX_0], &protectionType);
532     NAPIAshmem *napiAshmem = nullptr;
533     napi_unwrap(env, thisVar, (void **)&napiAshmem);
534     NAPI_ASSERT(env, napiAshmem != nullptr, "napiAshmem is null");
535     bool result = napiAshmem->GetAshmem()->SetProtection(protectionType);
536     napi_value napiValue = nullptr;
537     NAPI_CALL(env, napi_get_boolean(env, result, &napiValue));
538     return napiValue;
539 }
540 
SetProtectionType(napi_env env,napi_callback_info info)541 napi_value NAPIAshmem::SetProtectionType(napi_env env, napi_callback_info info)
542 {
543     napi_value thisVar = nullptr;
544     size_t argc = 1;
545     size_t argNum = 1;
546     napi_value argv[ARGV_LENGTH_1] = { 0 };
547     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
548     if (argc != argNum) {
549         ZLOGE(LOG_LABEL, "requires 1 parameter");
550         return napiErr.ThrowError(env, OHOS::errorDesc::CHECK_PARAM_ERROR);
551     }
552     napi_valuetype valueType = napi_null;
553     napi_typeof(env, argv[ARGV_INDEX_0], &valueType);
554     if (valueType != napi_number) {
555         ZLOGE(LOG_LABEL, "type mismatch for parameter 1");
556         return napiErr.ThrowError(env, OHOS::errorDesc::CHECK_PARAM_ERROR);
557     }
558     uint32_t protectionType = 0;
559     napi_get_value_uint32(env, argv[ARGV_INDEX_0], &protectionType);
560     NAPIAshmem *napiAshmem = nullptr;
561     napi_unwrap(env, thisVar, (void **)&napiAshmem);
562     if (napiAshmem == nullptr) {
563         ZLOGE(LOG_LABEL, "napiAshmem is null");
564         return napiErr.ThrowError(env, OHOS::errorDesc::OS_IOCTL_ERROR);
565     }
566     napiAshmem->GetAshmem()->SetProtection(protectionType);
567     napi_value result = nullptr;
568     napi_get_undefined(env, &result);
569     return result;
570 }
571 
UnmapAshmem(napi_env env,napi_callback_info info)572 napi_value NAPIAshmem::UnmapAshmem(napi_env env, napi_callback_info info)
573 {
574     napi_value thisVar = nullptr;
575     napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
576     NAPIAshmem *napiAshmem = nullptr;
577     napi_unwrap(env, thisVar, (void **)&napiAshmem);
578     NAPI_ASSERT(env, napiAshmem != nullptr, "napiAshmem is null");
579     napiAshmem->GetAshmem()->UnmapAshmem();
580     napi_value result = nullptr;
581     napi_get_undefined(env, &result);
582     return result;
583 }
584 
WriteToAshmem(napi_env env,napi_callback_info info)585 napi_value NAPIAshmem::WriteToAshmem(napi_env env, napi_callback_info info)
586 {
587     size_t argc = 3;
588     napi_value argv[ARGV_LENGTH_3] = {0};
589     napi_value thisVar = nullptr;
590     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
591     NAPI_ASSERT(env, argc == 3, "requires 3 parameter");
592     bool isArray = false;
593     napi_is_array(env, argv[ARGV_INDEX_0], &isArray);
594     NAPI_ASSERT(env, isArray == true, "type mismatch for parameter 1");
595     napi_valuetype valueType = napi_null;
596     napi_typeof(env, argv[ARGV_INDEX_1], &valueType);
597     NAPI_ASSERT(env, valueType == napi_number, "type mismatch for parameter 2");
598     napi_typeof(env, argv[ARGV_INDEX_2], &valueType);
599     NAPI_ASSERT(env, valueType == napi_number, "type mismatch for parameter 3");
600 
601     std::vector<int32_t> array;
602     uint32_t arrayLength = 0;
603     napi_get_array_length(env, argv[ARGV_INDEX_0], &arrayLength);
604 
605     for (size_t i = 0; i < arrayLength; i++) {
606         bool hasElement = false;
607         napi_has_element(env, argv[ARGV_INDEX_0], i, &hasElement);
608         NAPI_ASSERT(env, hasElement == true, "parameter check error");
609 
610         napi_value element = nullptr;
611         napi_get_element(env, argv[ARGV_INDEX_0], i, &element);
612 
613         int32_t value = 0;
614         napi_get_value_int32(env, element, &value);
615         array.push_back(value);
616     }
617 
618     int64_t size = 0;
619     napi_get_value_int64(env, argv[ARGV_INDEX_1], &size);
620     int64_t offset = 0;
621     napi_get_value_int64(env, argv[ARGV_INDEX_2], &offset);
622     NAPIAshmem *napiAshmem = nullptr;
623     napi_unwrap(env, thisVar, (void **)&napiAshmem);
624     NAPI_ASSERT(env, napiAshmem != nullptr, "napiAshmem is null");
625 
626     // need check size offset and capacity
627     napi_value napiValue = nullptr;
628     bool result = true;
629     uint32_t ashmemSize = (uint32_t)napiAshmem->GetAshmem()->GetAshmemSize();
630     if (size < 0 || size > (int64_t)(std::numeric_limits<int32_t>::max() / BYTE_SIZE_32) ||
631         offset < 0 || offset > (int64_t)(std::numeric_limits<int32_t>::max() / BYTE_SIZE_32) ||
632         (size * BYTE_SIZE_32 + offset * BYTE_SIZE_32) > ashmemSize) {
633         ZLOGE(LOG_LABEL, "invalid parameter, size:%{public}jd offset:%{public}jd", size, offset);
634         result = false;
635     } else {
636         result = napiAshmem->GetAshmem()->WriteToAshmem(array.data(), size * BYTE_SIZE_32, offset * BYTE_SIZE_32);
637     }
638     NAPI_CALL(env, napi_get_boolean(env, result, &napiValue));
639     return napiValue;
640 }
641 
WriteAshmem(napi_env env,napi_callback_info info)642 napi_value NAPIAshmem::WriteAshmem(napi_env env, napi_callback_info info)
643 {
644     size_t argc = 3;
645     napi_value argv[ARGV_LENGTH_3] = {0};
646     napi_value thisVar = nullptr;
647     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
648     napi_value checkArgsResult = CheckWriteAshmemParams(env, argc, argv);
649     if (checkArgsResult != nullptr) {
650         return checkArgsResult;
651     }
652 
653     std::vector<int32_t> array;
654     uint32_t arrayLength = 0;
655     napi_get_array_length(env, argv[ARGV_INDEX_0], &arrayLength);
656 
657     for (size_t i = 0; i < arrayLength; i++) {
658         bool hasElement = false;
659         napi_has_element(env, argv[ARGV_INDEX_0], i, &hasElement);
660         if (!hasElement) {
661             ZLOGE(LOG_LABEL, "parameter check error");
662             return napiErr.ThrowError(env, OHOS::errorDesc::CHECK_PARAM_ERROR);
663         }
664 
665         napi_value element = nullptr;
666         napi_get_element(env, argv[ARGV_INDEX_0], i, &element);
667 
668         int32_t value = 0;
669         napi_get_value_int32(env, element, &value);
670         array.push_back(value);
671     }
672 
673     int64_t size = 0;
674     napi_get_value_int64(env, argv[ARGV_INDEX_1], &size);
675     int64_t offset = 0;
676     napi_get_value_int64(env, argv[ARGV_INDEX_2], &offset);
677     NAPIAshmem *napiAshmem = nullptr;
678     napi_unwrap(env, thisVar, (void **)&napiAshmem);
679     if (napiAshmem == nullptr) {
680         ZLOGE(LOG_LABEL, "napiAshmem is null");
681         return napiErr.ThrowError(env, OHOS::errorDesc::WRITE_TO_ASHMEM_ERROR);
682     }
683 
684     // need check size offset and capacity
685     uint32_t ashmemSize = (uint32_t)napiAshmem->GetAshmem()->GetAshmemSize();
686     if (size < 0 || size > (int64_t)(std::numeric_limits<int32_t>::max() / BYTE_SIZE_32) ||
687         offset < 0 || offset > (int64_t)(std::numeric_limits<int32_t>::max() / BYTE_SIZE_32) ||
688         (size * BYTE_SIZE_32 + offset * BYTE_SIZE_32) > ashmemSize) {
689         ZLOGE(LOG_LABEL, "invalid parameter, size:%{public}jd offset:%{public}jd", size, offset);
690         return napiErr.ThrowError(env, OHOS::errorDesc::WRITE_TO_ASHMEM_ERROR);
691     }
692     napiAshmem->GetAshmem()->WriteToAshmem(array.data(), size * BYTE_SIZE_32, offset * BYTE_SIZE_32);
693     napi_value result = nullptr;
694     napi_get_undefined(env, &result);
695     return result;
696 }
697 
CheckWriteAshmemParams(napi_env env,size_t argc,napi_value * argv)698 napi_value NAPIAshmem::CheckWriteAshmemParams(napi_env env, size_t argc, napi_value* argv)
699 {
700     size_t argNum = 3;
701     if (argc != argNum) {
702         ZLOGE(LOG_LABEL, "requires 3 parameter");
703         return napiErr.ThrowError(env, OHOS::errorDesc::CHECK_PARAM_ERROR);
704     }
705     bool isArray = false;
706     napi_is_array(env, argv[ARGV_INDEX_0], &isArray);
707     if (!isArray) {
708         ZLOGE(LOG_LABEL, "type mismatch for parameter 1");
709         return napiErr.ThrowError(env, OHOS::errorDesc::CHECK_PARAM_ERROR);
710     }
711     napi_valuetype valueType = napi_null;
712     napi_typeof(env, argv[ARGV_INDEX_1], &valueType);
713     if (valueType != napi_number) {
714         ZLOGE(LOG_LABEL, "type mismatch for parameter 2");
715         return napiErr.ThrowError(env, OHOS::errorDesc::CHECK_PARAM_ERROR);
716     }
717     napi_typeof(env, argv[ARGV_INDEX_2], &valueType);
718     if (valueType != napi_number) {
719         ZLOGE(LOG_LABEL, "type mismatch for parameter 4");
720         return napiErr.ThrowError(env, OHOS::errorDesc::CHECK_PARAM_ERROR);
721     }
722     return nullptr;
723 }
724 
CheckWriteToAshmemParams(napi_env env,size_t argc,napi_value * argv)725 napi_value NAPIAshmem::CheckWriteToAshmemParams(napi_env env, size_t argc, napi_value* argv)
726 {
727     if (argc != ARGV_LENGTH_3) {
728         ZLOGE(LOG_LABEL, "requires 3 parameter");
729         return napiErr.ThrowError(env, OHOS::errorDesc::CHECK_PARAM_ERROR);
730     }
731 
732     bool isArrayBuffer = false;
733     napi_is_arraybuffer(env, argv[ARGV_INDEX_0], &isArrayBuffer);
734     if (!isArrayBuffer) {
735         ZLOGE(LOG_LABEL, "type mismatch for parameter 1, not ArrayBuffer");
736         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
737     }
738 
739     napi_valuetype valueType = napi_null;
740     napi_typeof(env, argv[ARGV_INDEX_1], &valueType);
741     if (valueType != napi_number) {
742         ZLOGE(LOG_LABEL, "type mismatch for parameter 2");
743         return napiErr.ThrowError(env, OHOS::errorDesc::CHECK_PARAM_ERROR);
744     }
745 
746     napi_typeof(env, argv[ARGV_INDEX_2], &valueType);
747     if (valueType != napi_number) {
748         ZLOGE(LOG_LABEL, "type mismatch for parameter 3");
749         return napiErr.ThrowError(env, OHOS::errorDesc::CHECK_PARAM_ERROR);
750     }
751     return nullptr;
752 }
753 
WriteDataToAshmem(napi_env env,napi_callback_info info)754 napi_value NAPIAshmem::WriteDataToAshmem(napi_env env, napi_callback_info info)
755 {
756     size_t argc = ARGV_LENGTH_3;
757     napi_value argv[ARGV_LENGTH_3] = {0};
758     napi_value thisVar = nullptr;
759     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
760     napi_value checkArgsResult = CheckWriteToAshmemParams(env, argc, argv);
761     if (checkArgsResult != nullptr) {
762         return checkArgsResult;
763     }
764 
765     void *data = nullptr;
766     size_t byteLength = 0;
767     napi_status isGet = napi_get_arraybuffer_info(env, argv[ARGV_INDEX_0], (void **)&data, &byteLength);
768     if (isGet != napi_ok) {
769         ZLOGE(LOG_LABEL, "arraybuffery get info failed");
770         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
771     }
772 
773     int64_t size = 0;
774     napi_get_value_int64(env, argv[ARGV_INDEX_1], &size);
775     int64_t offset = 0;
776     napi_get_value_int64(env, argv[ARGV_INDEX_2], &offset);
777     NAPIAshmem *napiAshmem = nullptr;
778     napi_unwrap(env, thisVar, (void **)&napiAshmem);
779     if (napiAshmem == nullptr) {
780         ZLOGE(LOG_LABEL, "napiAshmem is null");
781         return napiErr.ThrowError(env, OHOS::errorDesc::WRITE_TO_ASHMEM_ERROR);
782     }
783 
784     uint32_t ashmemSize = (uint32_t)napiAshmem->GetAshmem()->GetAshmemSize();
785     if (size <= 0 || size > std::numeric_limits<int32_t>::max() ||
786         offset < 0 || offset > std::numeric_limits<int32_t>::max() ||
787         (size + offset) > ashmemSize) {
788         ZLOGE(LOG_LABEL, "invalid parameter, size:%{public}" PRId64 " offset:%{public}" PRId64, size, offset);
789         return napiErr.ThrowError(env, OHOS::errorDesc::WRITE_TO_ASHMEM_ERROR);
790     }
791 
792     if (!napiAshmem->GetAshmem()->WriteToAshmem(data, size, offset)) {
793         ZLOGE(LOG_LABEL, "WriteToAshmem fail");
794         return napiErr.ThrowError(env, OHOS::errorDesc::WRITE_TO_ASHMEM_ERROR);
795     }
796     napi_value result = nullptr;
797     napi_get_undefined(env, &result);
798     return result;
799 }
800 
CheckReadFromAshmemParams(napi_env env,size_t argc,napi_value * argv)801 napi_value NAPIAshmem::CheckReadFromAshmemParams(napi_env env, size_t argc, napi_value* argv)
802 {
803     if (argc != ARGV_LENGTH_2) {
804         ZLOGE(LOG_LABEL, "requires 2 parameter");
805         return napiErr.ThrowError(env, OHOS::errorDesc::CHECK_PARAM_ERROR);
806     }
807     napi_valuetype valueType = napi_null;
808     napi_typeof(env, argv[ARGV_INDEX_0], &valueType);
809     if (valueType != napi_number) {
810         ZLOGE(LOG_LABEL, "type mismatch for parameter 1");
811         return napiErr.ThrowError(env, OHOS::errorDesc::CHECK_PARAM_ERROR);
812     }
813     napi_typeof(env, argv[ARGV_INDEX_1], &valueType);
814     if (valueType != napi_number) {
815         ZLOGE(LOG_LABEL, "type mismatch for parameter 2");
816         return napiErr.ThrowError(env, OHOS::errorDesc::CHECK_PARAM_ERROR);
817     }
818     return nullptr;
819 }
820 
ReadDataFromAshmem(napi_env env,napi_callback_info info)821 napi_value NAPIAshmem::ReadDataFromAshmem(napi_env env, napi_callback_info info)
822 {
823     size_t argc = ARGV_LENGTH_2;
824     napi_value argv[ARGV_LENGTH_2] = {0};
825     napi_value thisVar = nullptr;
826     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
827     napi_value checkArgsResult = CheckReadFromAshmemParams(env, argc, argv);
828     if (checkArgsResult != nullptr) {
829         return checkArgsResult;
830     }
831 
832     int64_t size = 0;
833     napi_get_value_int64(env, argv[ARGV_INDEX_0], &size);
834     int64_t offset = 0;
835     napi_get_value_int64(env, argv[ARGV_INDEX_1], &offset);
836     NAPIAshmem *napiAshmem = nullptr;
837     napi_unwrap(env, thisVar, (void **)&napiAshmem);
838     if (napiAshmem == nullptr) {
839         ZLOGE(LOG_LABEL, "napiAshmem is null");
840         return napiErr.ThrowError(env, OHOS::errorDesc::READ_FROM_ASHMEM_ERROR);
841     }
842     uint32_t ashmemSize = (uint32_t)napiAshmem->GetAshmem()->GetAshmemSize();
843     if (size <= 0 || size > std::numeric_limits<int32_t>::max() ||
844         offset < 0 || offset > std::numeric_limits<int32_t>::max() ||
845         (size + offset) > ashmemSize) {
846         ZLOGE(LOG_LABEL, "invalid parameter, size:%{public}" PRId64 " offset:%{public}" PRId64, size, offset);
847         return napiErr.ThrowError(env, OHOS::errorDesc::READ_FROM_ASHMEM_ERROR);
848     }
849 
850     const void *result = napiAshmem->GetAshmem()->ReadFromAshmem(size, offset);
851     if (result == nullptr) {
852         ZLOGE(LOG_LABEL, "ashmem->ReadFromAshmem returns null");
853         return napiErr.ThrowError(env, OHOS::errorDesc::READ_FROM_ASHMEM_ERROR);
854     }
855 
856     napi_value arrayBuffer = nullptr;
857     void *arrayBufferPtr = nullptr;
858     size_t bufferSize = static_cast<size_t>(size);
859     napi_status isCreateBufferOk = napi_create_arraybuffer(env, size, &arrayBufferPtr, &arrayBuffer);
860     if (isCreateBufferOk != napi_ok) {
861         ZLOGE(LOG_LABEL, "ReadDataFromAshmem create arrayBuffer failed");
862         return napiErr.ThrowError(env, errorDesc::READ_FROM_ASHMEM_ERROR);
863     }
864     errno_t status = memcpy_s(arrayBufferPtr, bufferSize, result, bufferSize);
865     if (status != EOK) {
866         ZLOGE(LOG_LABEL, "memcpy_s is failed");
867         return napiErr.ThrowError(env, OHOS::errorDesc::READ_FROM_ASHMEM_ERROR);
868     }
869     return arrayBuffer;
870 }
871 
AshmemExport(napi_env env,napi_value exports)872 napi_value NAPIAshmem::AshmemExport(napi_env env, napi_value exports)
873 {
874     const std::string className = "Ashmem";
875     napi_value exec = nullptr;
876     napi_create_int32(env, NAPIAshmem::PROT_EXEC, &exec);
877     napi_value none = nullptr;
878     napi_create_int32(env, NAPIAshmem::PROT_NONE, &none);
879     napi_value read = nullptr;
880     napi_create_int32(env, NAPIAshmem::PROT_READ, &read);
881     napi_value write = nullptr;
882     napi_create_int32(env, NAPIAshmem::PROT_WRITE, &write);
883     napi_property_descriptor properties[] = {
884         DECLARE_NAPI_STATIC_FUNCTION("createAshmem", NAPIAshmem::CreateAshmem),
885         DECLARE_NAPI_STATIC_FUNCTION("create", NAPIAshmem::Create),
886         DECLARE_NAPI_STATIC_FUNCTION("createAshmemFromExisting", NAPIAshmem::CreateAshmemFromExisting),
887         DECLARE_NAPI_FUNCTION("closeAshmem", NAPIAshmem::CloseAshmem),
888         DECLARE_NAPI_FUNCTION("getAshmemSize", NAPIAshmem::GetAshmemSize),
889         DECLARE_NAPI_FUNCTION("mapAshmem", NAPIAshmem::MapAshmem),
890         DECLARE_NAPI_FUNCTION("mapTypedAshmem", NAPIAshmem::MapTypedAshmem),
891         DECLARE_NAPI_FUNCTION("mapReadAndWriteAshmem", NAPIAshmem::MapReadAndWriteAshmem),
892         DECLARE_NAPI_FUNCTION("mapReadWriteAshmem", NAPIAshmem::MapReadWriteAshmem),
893         DECLARE_NAPI_FUNCTION("mapReadOnlyAshmem", NAPIAshmem::MapReadOnlyAshmem),
894         DECLARE_NAPI_FUNCTION("mapReadonlyAshmem", NAPIAshmem::MapReadonlyAshmem),
895         DECLARE_NAPI_FUNCTION("readFromAshmem", NAPIAshmem::ReadFromAshmem),
896         DECLARE_NAPI_FUNCTION("readAshmem", NAPIAshmem::ReadAshmem),
897         DECLARE_NAPI_FUNCTION("setProtection", NAPIAshmem::SetProtection),
898         DECLARE_NAPI_FUNCTION("setProtectionType", NAPIAshmem::SetProtectionType),
899         DECLARE_NAPI_FUNCTION("unmapAshmem", NAPIAshmem::UnmapAshmem),
900         DECLARE_NAPI_FUNCTION("writeToAshmem", NAPIAshmem::WriteToAshmem),
901         DECLARE_NAPI_FUNCTION("writeAshmem", NAPIAshmem::WriteAshmem),
902         DECLARE_NAPI_FUNCTION("writeDataToAshmem", NAPIAshmem::WriteDataToAshmem),
903         DECLARE_NAPI_FUNCTION("readDataFromAshmem", NAPIAshmem::ReadDataFromAshmem),
904         DECLARE_NAPI_STATIC_PROPERTY("PROT_EXEC", exec),
905         DECLARE_NAPI_STATIC_PROPERTY("PROT_NONE", none),
906         DECLARE_NAPI_STATIC_PROPERTY("PROT_READ", read),
907         DECLARE_NAPI_STATIC_PROPERTY("PROT_WRITE", write),
908     };
909     napi_value constructor = nullptr;
910     napi_define_class(env, className.c_str(), className.length(), Ashmem_JS_Constructor, nullptr,
911         sizeof(properties) / sizeof(properties[0]), properties, &constructor);
912     NAPI_ASSERT(env, constructor != nullptr, "define js class Ashmem failed");
913     napi_status status = napi_set_named_property(env, exports, "Ashmem", constructor);
914     NAPI_ASSERT(env, status == napi_ok, "set property Ashmem failed");
915     napi_value global = nullptr;
916     status = napi_get_global(env, &global);
917     NAPI_ASSERT(env, status == napi_ok, "get napi global failed");
918     status = napi_set_named_property(env, global, "AshmemConstructor_", constructor);
919     NAPI_ASSERT(env, status == napi_ok, "set Ashmem constructor failed");
920     return exports;
921 }
922 
Ashmem_JS_Constructor(napi_env env,napi_callback_info info)923 napi_value NAPIAshmem::Ashmem_JS_Constructor(napi_env env, napi_callback_info info)
924 {
925     napi_value thisVar = nullptr;
926     size_t argc = 2;
927     napi_value argv[ARGV_LENGTH_2] = { 0 };
928     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
929     NAPIAshmem *napiAshmem = nullptr;
930     if (argc == 0) {
931         napiAshmem = new (std::nothrow) NAPIAshmem();
932     } else {
933         NAPI_ASSERT(env, argc == 2, "requires 2 parameter");
934         napi_valuetype valueType = napi_null;
935         napi_typeof(env, argv[ARGV_INDEX_0], &valueType);
936         NAPI_ASSERT(env, valueType == napi_string, "type mismatch for parameter 1");
937         napi_typeof(env, argv[ARGV_INDEX_1], &valueType);
938         NAPI_ASSERT(env, valueType == napi_number, "type mismatch for parameter 2");
939         size_t bufferSize = 0;
940         size_t maxLen = 40960;
941         napi_get_value_string_utf8(env, argv[ARGV_INDEX_0], nullptr, 0, &bufferSize);
942         NAPI_ASSERT(env, bufferSize < maxLen, "string length too large");
943         char stringValue[bufferSize + 1];
944         size_t jsStringLength = 0;
945         napi_get_value_string_utf8(env, argv[ARGV_INDEX_0], stringValue, bufferSize + 1, &jsStringLength);
946         NAPI_ASSERT(env, jsStringLength == bufferSize, "string length wrong");
947         std::string ashmemName = stringValue;
948         uint32_t ashmemSize = 0;
949         napi_get_value_uint32(env, argv[ARGV_INDEX_1], &ashmemSize);
950         // new napi Ashmem
951         sptr<Ashmem> nativeAshmem = Ashmem::CreateAshmem(ashmemName.c_str(), ashmemSize);
952         NAPI_ASSERT(env, nativeAshmem != nullptr, "invalid parameters");
953         napiAshmem = new (std::nothrow) NAPIAshmem(nativeAshmem);
954     }
955     NAPI_ASSERT(env, napiAshmem != nullptr, "new NAPIAshmem failed");
956     // connect native object to js thisVar
957     napi_status status = napi_wrap(
958         env, thisVar, napiAshmem,
959         [](napi_env env, void *data, void *hint) {
960             ZLOGD(LOG_LABEL, "Ashmem destructed by js callback");
961             delete (reinterpret_cast<NAPIAshmem *>(data));
962         },
963         nullptr, nullptr);
964     if (status != napi_ok) {
965         delete napiAshmem;
966         NAPI_ASSERT(env, false, "wrap js Ashmem and native holder failed");
967     }
968     return thisVar;
969 }
970 } // namespace OHOS
971