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