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