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