1 /*
2 * Copyright (C) 2024 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 "IpcProxy.h"
17 #include <cstdlib>
18 #include <cstring>
19 #include <hilog/log.h>
20 #include <fcntl.h>
21 #include <future>
22 #include <unistd.h>
23 #include <thread>
24 #include <future>
25 #include <mutex>
26 #include <deque>
27 #include "napi/native_api.h"
28 #include "AbilityKit/native_child_process.h"
29 #include "ChildProcess.h"
30 #include "loghelper.h"
31 #include <vector>
32
33 #undef LOG_DOMAIN
34 #undef LOG_TAG
35 #define LOG_DOMAIN 0x3200
36 #define LOG_TAG "CHILD_TAG"
37
38 static ChildProcess g_childProcess;
39 static IpcProxy *g_ipcProxyPnt = nullptr;
40 static std::vector<IpcProxy*> g_ipcProxyPntObjects;
41 static std::promise<int> *g_promiseStartProcess = nullptr;
42
43 extern "C" {
44
NativeChildProcess_OnConnect()45 OHIPCRemoteStub* NativeChildProcess_OnConnect()
46 {
47 OH_LOG_INFO(LOG_APP, "Child process - OnConnect");
48 return g_childProcess.GetIpcStub();
49 }
50
NativeChildProcess_MainProc()51 void NativeChildProcess_MainProc()
52 {
53 OH_LOG_INFO(LOG_APP, "Child process - MainProc started");
54 g_childProcess.MainProc();
55 OH_LOG_INFO(LOG_APP, "Child process - MainProc end");
56 }
57
58 } // extern "C"
59
60 class ArkTsThread {
61 std::thread thread_;
62 napi_env env;
63 napi_ref on_message_func;
64 std::condition_variable cond;
65 std::mutex lock;
66 std::deque<std::function<void()>> jobs;
67 bool stopFlag = false;
68 public:
69 ArkTsThread();
70 ~ArkTsThread();
71 void CallFunc();
72 };
73
ArkTsThread()74 ArkTsThread::ArkTsThread()
75 {
76 auto waiter = std::promise<bool>();
77 this->thread_ = std::thread([&]() {
78 napi_create_ark_runtime(&this->env);
79 auto env = this->env;
80
81 napi_value worker_utils;
82 napi_load_module_with_info(env, "entry/src/main/ets/pages/worker",
83 "com.example.capichildprocesstest/entry", &worker_utils);
84 napi_value on_message_func;
85 auto ret = napi_get_named_property(env, worker_utils, "onMessage", &on_message_func);
86 napi_create_reference(env, on_message_func, 1, &this->on_message_func);
87 waiter.set_value(true);
88
89 while (!stopFlag) {
90 auto l = std::unique_lock<std::mutex>(this->lock);
91 cond.wait(l, [this] {return stopFlag;});
92 for (const auto job : this->jobs) {
93 job();
94 }
95 this->jobs.clear();
96 }
97 napi_destroy_ark_runtime(&this->env);
98 });
99 waiter.get_future().wait();
100 }
101
~ArkTsThread()102 ArkTsThread::~ArkTsThread()
103 {
104 {
105 auto l = std::unique_lock<std::mutex>(this->lock);
106 stopFlag = true;
107 }
108 cond.notify_all();
109 if (this->thread_.joinable()) {
110 this->thread_.join();
111 }
112 }
113
CallFunc()114 void ArkTsThread::CallFunc()
115 {
116 auto l = std::unique_lock<std::mutex>(this->lock);
117 this->jobs.push_back([this]() {
118 napi_value on_message_func;
119 napi_get_reference_value(this->env, this->on_message_func, &on_message_func);
120 napi_value ret;
121 napi_call_function(this->env, nullptr, on_message_func, 0, nullptr, &ret);
122 });
123 this->cond.notify_all();
124 }
125
126 namespace {
127 ArkTsThread *thread;
128 }
129
OnNativeChildProcessStarted(int errCode,OHIPCRemoteProxy * remoteProxy)130 static void OnNativeChildProcessStarted(int errCode, OHIPCRemoteProxy *remoteProxy)
131 {
132 OH_LOG_INFO(LOG_APP, "Main process - OnNativeChildProcessStarted %{public}d", errCode);
133 g_ipcProxyPnt = new (std::nothrow) IpcProxy(remoteProxy);
134 if (g_ipcProxyPnt == nullptr) {
135 OH_LOG_ERROR(LOG_APP, "Main process - Alloc ipc proxy object failed!");
136 OH_IPCRemoteProxy_Destroy(remoteProxy);
137 } else {
138 g_ipcProxyPntObjects.push_back(g_ipcProxyPnt);
139 }
140
141 if (g_promiseStartProcess != nullptr) {
142 g_promiseStartProcess->set_value(errCode);
143 }
144 }
145
OnNativeChildProcessExit(int32_t pid,int32_t signal)146 static void OnNativeChildProcessExit(int32_t pid, int32_t signal)
147 {
148 OH_LOG_INFO(LOG_APP, "child exit, pid:%{public}d, signal:%{public}d", pid, signal);
149 thread = new ArkTsThread();
150 thread->CallFunc();
151 delete thread;
152 thread = nullptr;
153 }
154
ChildProcessAdd(napi_env env,napi_callback_info info)155 static napi_value ChildProcessAdd(napi_env env, napi_callback_info info)
156 {
157 int32_t result = INT32_MIN;
158 if (g_ipcProxyPnt != nullptr) {
159 size_t argc = 2;
160 napi_value args[2] = { nullptr };
161 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
162 int32_t value0;
163 napi_get_value_int32(env, args[0], &value0);
164 int32_t value1;
165 napi_get_value_int32(env, args[1], &value1);
166
167 result = g_ipcProxyPnt->Add(value0, value1);
168 OH_LOG_INFO(LOG_APP, "Main process - ChildProcessAdd %{public}d+%{public}d=%{public}d",
169 value0, value1, result);
170 } else {
171 OH_LOG_ERROR(LOG_APP, "Main process - Child process not started");
172 }
173
174 napi_value sumNapi;
175 napi_create_int32(env, result, &sumNapi);
176 return sumNapi;
177 }
178
StartNativeChildProcess(napi_env env,napi_callback_info info)179 static napi_value StartNativeChildProcess(napi_env env, napi_callback_info info)
180 {
181 std::promise<int> promise;
182 g_promiseStartProcess = &promise;
183
184 size_t argc = 1;
185 napi_value args[1] = { nullptr };
186 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
187
188 char libName[64];
189 size_t nameLen;
190 napi_get_value_string_utf8(env, args[0], libName, sizeof(libName), &nameLen);
191
192 int32_t ret = OH_Ability_CreateNativeChildProcess(libName, OnNativeChildProcessStarted);
193 OH_LOG_INFO(LOG_APP, "Main process - StartNativeChildProcess Lib:%{public}s ret:%{public}d", libName, ret);
194
195 if (ret == NCP_NO_ERROR) {
196 auto future = promise.get_future();
197 OH_LOG_INFO(LOG_APP, "Main process - Wait for call back");
198 ret = future.get();
199 }
200
201 g_promiseStartProcess = nullptr;
202 napi_value napiRet;
203 napi_create_int32(env, ret, &napiRet);
204 return napiRet;
205 }
206
RequestExitChildProcess(napi_env env,napi_callback_info info)207 static napi_value RequestExitChildProcess(napi_env env, napi_callback_info info)
208 {
209 int32_t ret = 0;
210 size_t argc = 1;
211 napi_value args[1] = { nullptr };
212 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
213 int32_t value0;
214 napi_get_value_int32(env, args[0], &value0);
215 if (g_ipcProxyPnt != nullptr && g_ipcProxyPnt->RequestExitChildProcess(value0)) {
216 ret = 1;
217 delete g_ipcProxyPnt;
218 g_ipcProxyPnt = nullptr;
219 OH_LOG_INFO(LOG_APP, "Main process - RequestExitChildProcess successed");
220
221 g_ipcProxyPntObjects.pop_back();
222 if (!g_ipcProxyPntObjects.empty()) {
223 OH_LOG_INFO(LOG_APP, "Main process - RequestExitChildProcess get g_ipcProxyPnt");
224 g_ipcProxyPnt = g_ipcProxyPntObjects.back();
225 }
226 }
227
228 napi_value napiRet;
229 napi_create_int32(env, ret, &napiRet);
230 return napiRet;
231 }
232
CallApiWithNullCallback(napi_env env,napi_callback_info info)233 static napi_value CallApiWithNullCallback(napi_env env, napi_callback_info info)
234 {
235 int32_t ret = OH_Ability_CreateNativeChildProcess("libentry.so", nullptr);
236 napi_value napiRet;
237 napi_create_int32(env, ret, &napiRet);
238 return napiRet;
239 }
240
CallApiWithNullLibName(napi_env env,napi_callback_info info)241 static napi_value CallApiWithNullLibName(napi_env env, napi_callback_info info)
242 {
243 int32_t ret = OH_Ability_CreateNativeChildProcess(nullptr, OnNativeChildProcessStarted);
244 napi_value napiRet;
245 napi_create_int32(env, ret, &napiRet);
246 return napiRet;
247 }
248
CallApiWithNull(napi_env env,napi_callback_info info)249 static napi_value CallApiWithNull(napi_env env, napi_callback_info info)
250 {
251 int32_t ret = OH_Ability_CreateNativeChildProcess(nullptr, nullptr);
252 napi_value napiRet;
253 napi_create_int32(env, ret, &napiRet);
254 return napiRet;
255 }
256
ChildProcessStartNewProcess(napi_env env,napi_callback_info info)257 static napi_value ChildProcessStartNewProcess(napi_env env, napi_callback_info info)
258 {
259 int32_t ret = INT32_MIN;
260 if (g_ipcProxyPnt != nullptr) {
261 ret = g_ipcProxyPnt->StartNativeChildProcess();
262 OH_LOG_INFO(LOG_APP, "Main process - StartNativeChildProcess ret:%{public}d", ret);
263 }
264
265 napi_value napiRet;
266 napi_create_int32(env, ret, &napiRet);
267 return napiRet;
268 }
269
BusyTest(napi_env env,napi_callback_info info)270 static napi_value BusyTest(napi_env env, napi_callback_info info)
271 {
272 napi_value napiRet;
273 std::promise<int> promise;
274 g_promiseStartProcess = &promise;
275 int32_t ret = OH_Ability_CreateNativeChildProcess("libbusytest.so", OnNativeChildProcessStarted);
276 if (ret != NCP_NO_ERROR) {
277 OH_LOG_INFO(LOG_APP, "Main process - StartNativeChildProcess for busy test failed! ret:%{public}d", ret);
278 napi_create_int32(env, ret, &napiRet);
279 return napiRet;
280 }
281
282 ret = OH_Ability_CreateNativeChildProcess("libentry.so", OnNativeChildProcessStarted);
283
284 auto future = promise.get_future();
285 OH_LOG_INFO(LOG_APP, "Main process - Wait for busy test call back");
286 future.wait();
287
288 g_promiseStartProcess = nullptr;
289 napi_create_int32(env, ret, &napiRet);
290 return napiRet;
291 }
292
StartChildWithArgs(NativeChildProcess_IsolationMode mode)293 static Ability_NativeChildProcess_ErrCode StartChildWithArgs(NativeChildProcess_IsolationMode mode)
294 {
295 int32_t pid = -1;
296 NativeChildProcess_Args args;
297 auto testParam = "testEntryParams";
298 args.entryParams = (char*)malloc(sizeof(char) * strlen(testParam) + 1);
299 (void)strcpy(args.entryParams, testParam);
300
301 auto fd1Name = "fd1";
302 args.fdList.head = (NativeChildProcess_Fd*)malloc(sizeof(NativeChildProcess_Fd));
303 args.fdList.head->fdName = (char*)malloc(sizeof(char) * strlen(fd1Name) + 1);
304 (void)strcpy(args.fdList.head->fdName, fd1Name);
305
306 auto path = "data/storage/el2/base/files/test.txt";
307 int32_t fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0644);
308 auto testString = "test";
309 write(fd, testString, strlen(testString));
310 close(fd);
311 fd = open(path, O_RDWR | O_TRUNC, 0644);
312 args.fdList.head->fd = fd;
313 args.fdList.head->next = NULL;
314
315 NativeChildProcess_Options options = {
316 .isolationMode = mode
317 };
318 OH_LOG_INFO(LOG_APP, "===================Ability_NativeChildProcess before");
319 Ability_NativeChildProcess_ErrCode ret = OH_Ability_StartNativeChildProcess(
320 "libentry.so:Main", args, options, &pid);
321 OH_LOG_INFO(LOG_APP, "===================Ability_NativeChildProcess_ErrCode: %{public}d", ret);
322 close(fd);
323 return ret;
324 }
325
StartChildWithNoArgs()326 static Ability_NativeChildProcess_ErrCode StartChildWithNoArgs()
327 {
328 int32_t pid = -1;
329 NativeChildProcess_Args args;
330 args.entryParams = NULL;
331 args.fdList.head = NULL;
332
333 NativeChildProcess_Options options = {
334 .isolationMode = NCP_ISOLATION_MODE_ISOLATED
335 };
336 OH_LOG_INFO(LOG_APP, "===================Ability_NativeChildProcess before");
337 Ability_NativeChildProcess_ErrCode ret = OH_Ability_StartNativeChildProcess(
338 "libentry.so:Main", args, options, &pid);
339 OH_LOG_INFO(LOG_APP, "===================Ability_NativeChildProcess_ErrCode: %{public}d", ret);
340 return ret;
341 }
342
StartChildIsolated(napi_env env,napi_callback_info info)343 static napi_value StartChildIsolated(napi_env env, napi_callback_info info)
344 {
345 OH_LOG_INFO(LOG_APP, "===================StartChildIsolated");
346 int32_t ret = static_cast<int32_t>(StartChildWithArgs(NCP_ISOLATION_MODE_ISOLATED));
347 napi_value napiRet;
348 napi_create_int32(env, ret, &napiRet);
349 return napiRet;
350 }
351
StartChildNormal(napi_env env,napi_callback_info info)352 static napi_value StartChildNormal(napi_env env, napi_callback_info info)
353 {
354 OH_LOG_INFO(LOG_APP, "===================StartChildNormal");
355 int32_t ret = static_cast<int32_t>(StartChildWithArgs(NCP_ISOLATION_MODE_NORMAL));
356 napi_value napiRet;
357 napi_create_int32(env, ret, &napiRet);
358 return napiRet;
359 }
360
361
StartChildNoArgs(napi_env env,napi_callback_info info)362 static napi_value StartChildNoArgs(napi_env env, napi_callback_info info)
363 {
364 OH_LOG_INFO(LOG_APP, "===================StartChildWithNoArgs");
365 int32_t ret = static_cast<int32_t>(StartChildWithNoArgs());
366 OH_LOG_INFO(LOG_APP, "===================StartChildWithNoArgs end: %{public}d", ret);
367 napi_value napiRet;
368 napi_create_int32(env, ret, &napiRet);
369 return napiRet;
370 }
371
RegisterNativeChildExit(napi_env env,napi_callback_info info)372 static napi_value RegisterNativeChildExit(napi_env env, napi_callback_info info)
373 {
374 OH_LOG_INFO(LOG_APP, "===================RegisterNativeChildExit before");
375 Ability_NativeChildProcess_ErrCode ret = OH_Ability_RegisterNativeChildProcessExitCallback(
376 OnNativeChildProcessExit);
377 OH_LOG_INFO(LOG_APP, "===================Ability_NativeChildProcess_ErrCode: %{public}d", ret);
378 napi_value napiRet;
379 napi_create_int32(env, ret, &napiRet);
380 return napiRet;
381 }
382
UnregisterNativeChildExit(napi_env env,napi_callback_info info)383 static napi_value UnregisterNativeChildExit(napi_env env, napi_callback_info info)
384 {
385 OH_LOG_INFO(LOG_APP, "===================UnregisterNativeChildExit before");
386 Ability_NativeChildProcess_ErrCode ret = OH_Ability_UnregisterNativeChildProcessExitCallback(
387 OnNativeChildProcessExit);
388 OH_LOG_INFO(LOG_APP, "===================Ability_NativeChildProcess_ErrCode: %{public}d", ret);
389 napi_value napiRet;
390 napi_create_int32(env, ret, &napiRet);
391 return napiRet;
392 }
393
394
395
CreateThread(napi_env env,napi_callback_info info)396 static napi_value CreateThread(napi_env env, napi_callback_info info)
397 {
398 thread = new ArkTsThread();
399 return {};
400 }
401
DestroyThread(napi_env env,napi_callback_info info)402 static napi_value DestroyThread(napi_env env, napi_callback_info info)
403 {
404 if (thread) {
405 delete thread;
406 thread = nullptr;
407 }
408
409 return {};
410 }
CreateNativeChildProcessWithConfigs(napi_env env,napi_callback_info info)411 static napi_value CreateNativeChildProcessWithConfigs(napi_env env, napi_callback_info info)
412 {
413 std::promise<int> promise;
414 g_promiseStartProcess = &promise;
415
416 size_t argc = 1;
417 napi_value args[1] = { nullptr };
418 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
419
420 char libName[64];
421 size_t nameLen;
422 napi_get_value_string_utf8(env, args[0], libName, sizeof(libName), &nameLen);
423
424 Ability_ChildProcessConfigs* configs = OH_Ability_CreateChildProcessConfigs();
425 Ability_NativeChildProcess_ErrCode errCode =
426 OH_Ability_ChildProcessConfigs_SetProcessName(configs, "abc_123");
427 if(errCode != NCP_NO_ERROR) {
428 OH_LOG_ERROR(LOG_APP, "SetProcessName failed, errCode=%{public}d", errCode);
429 }
430
431 int32_t ret = OH_Ability_CreateNativeChildProcessWithConfigs(libName, configs, OnNativeChildProcessStarted);
432 OH_LOG_INFO(LOG_APP, "Main process - StartNativeChildProcess Lib:%{public}s ret:%{public}d", libName, ret);
433
434 if (ret == NCP_NO_ERROR) {
435 auto future = promise.get_future();
436 OH_LOG_INFO(LOG_APP, "Main process - Wait for call back");
437 ret = future.get();
438 }
439
440 g_promiseStartProcess = nullptr;
441 napi_value napiRet;
442 napi_create_int32(env, ret, &napiRet);
443 return napiRet;
444 }
445
CreateNativeChildProcessWithConfigsLibNamenullptr(napi_env env,napi_callback_info info)446 static napi_value CreateNativeChildProcessWithConfigsLibNamenullptr(napi_env env, napi_callback_info info)
447 {
448 Ability_ChildProcessConfigs* configs = OH_Ability_CreateChildProcessConfigs();
449 Ability_NativeChildProcess_ErrCode errCode =
450 OH_Ability_ChildProcessConfigs_SetProcessName(configs, "abc_123");
451 if(errCode != NCP_NO_ERROR) {
452 OH_LOG_ERROR(LOG_APP, "SetProcessName failed, errCode=%{public}d", errCode);
453 }
454
455 int32_t ret = OH_Ability_CreateNativeChildProcessWithConfigs(nullptr, configs, OnNativeChildProcessStarted);
456 napi_value napiRet;
457 napi_create_int32(env, ret, &napiRet);
458 return napiRet;
459 }
460
CreateNativeChildProcessWithConfigsNullCallback(napi_env env,napi_callback_info info)461 static napi_value CreateNativeChildProcessWithConfigsNullCallback(napi_env env, napi_callback_info info)
462 {
463 Ability_ChildProcessConfigs* configs = OH_Ability_CreateChildProcessConfigs();
464 Ability_NativeChildProcess_ErrCode errCode =
465 OH_Ability_ChildProcessConfigs_SetProcessName(configs, "abc_123");
466 if(errCode != NCP_NO_ERROR) {
467 OH_LOG_ERROR(LOG_APP, "SetProcessName failed, errCode=%{public}d", errCode);
468 }
469
470 int32_t ret = OH_Ability_CreateNativeChildProcessWithConfigs("libentry.so", configs, nullptr);
471 napi_value napiRet;
472 napi_create_int32(env, ret, &napiRet);
473 return napiRet;
474 }
475
StartNativeChildProcessWithConfigs(napi_env env,napi_callback_info info)476 static napi_value StartNativeChildProcessWithConfigs(napi_env env, napi_callback_info info)
477 {
478 size_t argc = 1;
479 napi_value args_str[1] = { nullptr };
480 napi_get_cb_info(env, info, &argc, args_str, nullptr, nullptr);
481
482 char entry[64];
483 size_t nameLen;
484 napi_get_value_string_utf8(env, args_str[0], entry, sizeof(entry), &nameLen);
485
486 Ability_ChildProcessConfigs* configs = OH_Ability_CreateChildProcessConfigs();
487 Ability_NativeChildProcess_ErrCode errCode =
488 OH_Ability_ChildProcessConfigs_SetProcessName(configs, "abc_123");
489 if(errCode != NCP_NO_ERROR) {
490 OH_LOG_ERROR(LOG_APP, "SetProcessName failed, errCode=%{public}d", errCode);
491 }
492
493 int32_t pid = -1;
494 NativeChildProcess_Args args;
495 auto testParam = "testEntryParams";
496 args.entryParams = (char*)malloc(sizeof(char) * strlen(testParam) + 1);
497 (void)strcpy(args.entryParams, testParam);
498
499 auto fd1Name = "fd1";
500 args.fdList.head = (NativeChildProcess_Fd*)malloc(sizeof(NativeChildProcess_Fd));
501 args.fdList.head->fdName = (char*)malloc(sizeof(char) * strlen(fd1Name) + 1);
502 (void)strcpy(args.fdList.head->fdName, fd1Name);
503
504 auto path = "data/storage/el2/base/files/test.txt";
505 int32_t fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0644);
506 auto testString = "test";
507 write(fd, testString, strlen(testString));
508 close(fd);
509 fd = open(path, O_RDWR | O_TRUNC, 0644);
510 args.fdList.head->fd = fd;
511 args.fdList.head->next = NULL;
512
513 int32_t ret = OH_Ability_StartNativeChildProcessWithConfigs(entry, args, configs, &pid);
514
515 OH_LOG_INFO(LOG_APP, "Main process - StartNativeChildProcessWithConfigs entry:%{public}s ret:%{public}d", entry, ret);
516
517 free(args.entryParams);
518 free(args.fdList.head->fdName);
519 free(args.fdList.head);
520 close(fd);
521
522 if (ret == NCP_NO_ERROR) {
523 ret = pid;
524 }
525
526 napi_value napiRet;
527 napi_create_int32(env, ret, &napiRet);
528 return napiRet;
529 }
530
StartNativeChildProcessWithConfigsEntryNull(napi_env env,napi_callback_info info)531 static napi_value StartNativeChildProcessWithConfigsEntryNull(napi_env env, napi_callback_info info)
532 {
533 std::promise<int> promise;
534 g_promiseStartProcess = &promise;
535
536 Ability_ChildProcessConfigs* configs = OH_Ability_CreateChildProcessConfigs();
537 Ability_NativeChildProcess_ErrCode errCode =
538 OH_Ability_ChildProcessConfigs_SetProcessName(configs, "abc_123");
539 if(errCode != NCP_NO_ERROR) {
540 OH_LOG_ERROR(LOG_APP, "SetProcessName failed, errCode=%{public}d", errCode);
541 }
542
543 int32_t pid = -1;
544 NativeChildProcess_Args args;
545 args.entryParams = (char*) malloc (sizeof(char) * 11);
546 (void)strcpy(args.entryParams, "testParams");
547
548 args.fdList.head = (NativeChildProcess_Fd *)malloc(sizeof(NativeChildProcess_Fd));
549 args.fdList.head->fdName = (char *)malloc(sizeof(char) * 5);
550 (void)strcpy(args.fdList.head->fdName, "fd1");
551 int32_t fd = open("/data/storage/el2/base/haps/entry/files/test0.txt", O_RDWR | O_CREAT, 0644);
552 write(fd, "test", 4);
553 close(fd);
554
555 fd = open("/data/storage/el2/base/haps/entry/files/test0.txt", O_RDWR | O_CREAT, 0644);
556 args.fdList.head->fd = fd;
557 args.fdList.head->next = NULL;
558
559 int32_t ret = OH_Ability_StartNativeChildProcessWithConfigs(nullptr, args, configs, &pid);
560
561 //OH_LOG_INFO(LOG_APP, "Main process - StartNativeChildProcessWithConfigs entry:%{public}s ret:%{public}d", entry, ret);
562
563 free(args.entryParams);
564 free(args.fdList.head->fdName);
565 free(args.fdList.head);
566 close(fd);
567
568 if (ret == NCP_NO_ERROR) {
569 ret = pid;
570 }
571
572 napi_value napiRet;
573 napi_create_int32(env, ret, &napiRet);
574 return napiRet;
575 }
576
StartNativeChildProcessWithConfigsEntryParams200K(napi_env env,napi_callback_info info)577 static napi_value StartNativeChildProcessWithConfigsEntryParams200K(napi_env env, napi_callback_info info)
578 {
579 std::promise<int> promise;
580 g_promiseStartProcess = &promise;
581
582 Ability_ChildProcessConfigs* configs = OH_Ability_CreateChildProcessConfigs();
583 Ability_NativeChildProcess_ErrCode errCode =
584 OH_Ability_ChildProcessConfigs_SetProcessName(configs, "abc_123");
585 if(errCode != NCP_NO_ERROR) {
586 OH_LOG_ERROR(LOG_APP, "SetProcessName failed, errCode=%{public}d", errCode);
587 }
588
589 int32_t pid = -1;
590 const size_t size = 200*1024;
591 NativeChildProcess_Args args;
592 auto testParam = "testEntryParams";
593 args.entryParams = (char*)malloc(sizeof(char) * strlen(testParam) + 1);
594 (void)strcpy(args.entryParams, testParam);
595
596 auto fd1Name = "fd1";
597 args.fdList.head = (NativeChildProcess_Fd*)malloc(sizeof(NativeChildProcess_Fd));
598 args.fdList.head->fdName = (char*)malloc(sizeof(char) * strlen(fd1Name) + 1);
599 (void)strcpy(args.fdList.head->fdName, fd1Name);
600
601 auto path = "data/storage/el2/base/files/test.txt";
602 int32_t fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0644);
603 auto testString = "test";
604 write(fd, testString, strlen(testString));
605 close(fd);
606 fd = open(path, O_RDWR | O_TRUNC, 0644);
607 args.fdList.head->fd = fd;
608 args.fdList.head->next = NULL;
609
610 int32_t ret = OH_Ability_StartNativeChildProcessWithConfigs("libentry.so:Main", args, configs, &pid);
611
612 OH_LOG_INFO(LOG_APP, "Main process - StartNativeChildProcessWithConfigs entry:%{public}s ret:%{public}d", "libentry.so:Main", ret);
613
614 free(args.entryParams);
615 free(args.fdList.head->fdName);
616 free(args.fdList.head);
617 close(fd);
618
619 if (ret == NCP_NO_ERROR) {
620 ret = pid;
621 }
622
623 napi_value napiRet;
624 napi_create_int32(env, ret, &napiRet);
625 return napiRet;
626 }
627
StartNativeChildProcessWithConfigsFdlistNum17(napi_env env,napi_callback_info info)628 static napi_value StartNativeChildProcessWithConfigsFdlistNum17(napi_env env, napi_callback_info info)
629 {
630 std::promise<int> promise;
631 g_promiseStartProcess = &promise;
632
633 Ability_ChildProcessConfigs* configs = OH_Ability_CreateChildProcessConfigs();
634 Ability_NativeChildProcess_ErrCode errCode =
635 OH_Ability_ChildProcessConfigs_SetProcessName(configs, "abc_123");
636 if(errCode != NCP_NO_ERROR) {
637 OH_LOG_ERROR(LOG_APP, "SetProcessName failed, errCode=%{public}d", errCode);
638 }
639
640 int32_t pid = -1;
641 const size_t size = 200*1024;
642 NativeChildProcess_Args args;
643 args.entryParams = (char*) malloc (sizeof(char) * size);
644 for(int i=0; i < size; i++){
645 args.entryParams[i] = 'a';
646 }
647
648 args.fdList.head = (NativeChildProcess_Fd *)malloc(sizeof(NativeChildProcess_Fd));
649 args.fdList.head->fdName = (char *)malloc(sizeof(char) * 5);
650 (void)strcpy(args.fdList.head->fdName, "fd1");
651 int32_t fd = open("/data/storage/el2/base/haps/entry/files/test0.txt", O_RDWR | O_CREAT, 0644);
652 write(fd, "test", 4);
653 close(fd);
654
655 fd = open("/data/storage/el2/base/haps/entry/files/test0.txt", O_RDWR | O_CREAT, 0644);
656 args.fdList.head->fd = fd;
657 int32_t MAX_fd_count = 17;
658 NativeChildProcess_Fd* tmp_node = args.fdList.head;
659 for (int32_t i = 1; i < MAX_fd_count; i++) {
660 tmp_node->next = (NativeChildProcess_Fd *)malloc(sizeof(NativeChildProcess_Fd));
661 tmp_node = tmp_node->next;
662 tmp_node->fdName = (char *)malloc(sizeof(char)*3);
663 std::string tmp_fdName = "fd" + std::to_string(i);
664 (void)strcpy(tmp_node->fdName, tmp_fdName.c_str());
665 std::string tmp_filename = "/data/storage/el2/base/haps/entry/files/test" + std::to_string(i) + "txt";
666 int32_t tmp_fd = open(tmp_filename.c_str(), O_RDWR | O_CREAT, 0644);
667 tmp_node->fd = tmp_fd;
668 }
669
670 tmp_node->next = NULL;
671
672 int32_t ret = OH_Ability_StartNativeChildProcessWithConfigs("libentry.so:Main", args, configs, &pid);
673
674 OH_LOG_INFO(LOG_APP, "Main process - StartNativeChildProcessWithConfigs entry:%{public}s ret:%{public}d", "libentry.so:Main", ret);
675
676 for(NativeChildProcess_Fd* node = args.fdList.head; node != NULL; ){
677 NativeChildProcess_Fd* next_node = node->next;
678 close(node->fd);
679 free(node->fdName);
680 free(node);
681 node = next_node;
682 }
683 free(args.entryParams);
684
685 if (ret == NCP_NO_ERROR) {
686 ret = pid;
687 }
688
689 napi_value napiRet;
690 napi_create_int32(env, ret, &napiRet);
691 return napiRet;
692 }
693
SetIsolationModeConfigsNullptr(napi_env env,napi_callback_info info)694 static napi_value SetIsolationModeConfigsNullptr(napi_env env, napi_callback_info info)
695 {
696 Ability_NativeChildProcess_ErrCode ret =
697 OH_Ability_ChildProcessConfigs_SetIsolationMode(nullptr, NCP_ISOLATION_MODE_ISOLATED);
698
699 napi_value napiRet;
700 napi_create_int32(env, ret, &napiRet);
701 return napiRet;
702 }
703
SetProcessName(napi_env env,napi_callback_info info)704 static napi_value SetProcessName(napi_env env, napi_callback_info info)
705 {
706 size_t argc = 1;
707 napi_value args[1] = { nullptr };
708 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
709
710 char processName[70];
711 size_t nameLen;
712 napi_get_value_string_utf8(env, args[0], processName, sizeof(processName), &nameLen);
713
714 Ability_ChildProcessConfigs* configs = OH_Ability_CreateChildProcessConfigs();
715 Ability_NativeChildProcess_ErrCode ret =
716 OH_Ability_ChildProcessConfigs_SetProcessName(configs, processName);
717 if(ret != NCP_NO_ERROR) {
718 OH_LOG_ERROR(LOG_APP, "SetProcessName failed, errCode=%{public}d", ret);
719 }
720
721 napi_value napiRet;
722 napi_create_int32(env, ret, &napiRet);
723 return napiRet;
724 }
725
SetProcessNameConfigsNullptr(napi_env env,napi_callback_info info)726 static napi_value SetProcessNameConfigsNullptr(napi_env env, napi_callback_info info)
727 {
728 Ability_NativeChildProcess_ErrCode ret =
729 OH_Ability_ChildProcessConfigs_SetProcessName(nullptr, "abc_123");
730 if(ret != NCP_NO_ERROR) {
731 OH_LOG_ERROR(LOG_APP, "SetProcessName failed, errCode=%{public}d", ret);
732 }
733
734 napi_value napiRet;
735 napi_create_int32(env, ret, &napiRet);
736 return napiRet;
737 }
738
DestroyChildProcessConfigs(napi_env env,napi_callback_info info)739 static napi_value DestroyChildProcessConfigs(napi_env env, napi_callback_info info)
740 {
741 Ability_ChildProcessConfigs* configs = OH_Ability_CreateChildProcessConfigs();
742 Ability_NativeChildProcess_ErrCode ret =
743 OH_Ability_DestroyChildProcessConfigs(configs);
744
745 napi_value napiRet;
746 napi_create_int32(env, ret, &napiRet);
747 return napiRet;
748 }
749
DestroyChildProcessConfigsNullptr(napi_env env,napi_callback_info info)750 static napi_value DestroyChildProcessConfigsNullptr(napi_env env, napi_callback_info info)
751 {
752 Ability_NativeChildProcess_ErrCode ret =
753 OH_Ability_DestroyChildProcessConfigs(nullptr);
754
755 napi_value napiRet;
756 napi_create_int32(env, ret, &napiRet);
757 return napiRet;
758 }
759
760
761 EXTERN_C_START
Init(napi_env env,napi_value exports)762 static napi_value Init(napi_env env, napi_value exports)
763 {
764 napi_property_descriptor desc[] = {
765 { "childProcessAdd", nullptr, ChildProcessAdd, nullptr, nullptr, nullptr, napi_default, nullptr },
766 { "startNativeChildProcess", nullptr, StartNativeChildProcess,
767 nullptr, nullptr, nullptr, napi_default, nullptr },
768 { "requestExitChildProcess", nullptr, RequestExitChildProcess,
769 nullptr, nullptr, nullptr, napi_default, nullptr },
770 { "callApiWithNullCallback", nullptr, CallApiWithNullCallback,
771 nullptr, nullptr, nullptr, napi_default, nullptr },
772 { "callApiWithNullLibName", nullptr, CallApiWithNullLibName,
773 nullptr, nullptr, nullptr, napi_default, nullptr },
774 { "callApiWithNull", nullptr, CallApiWithNull,
775 nullptr, nullptr, nullptr, napi_default, nullptr },
776 { "childProcessStartNewProcess", nullptr, ChildProcessStartNewProcess,
777 nullptr, nullptr, nullptr, napi_default, nullptr },
778 { "busyTest", nullptr, BusyTest,
779 nullptr, nullptr, nullptr, napi_default, nullptr },
780 { "startChildIsolated", nullptr, StartChildIsolated,
781 nullptr, nullptr, nullptr, napi_default, nullptr },
782 { "startChildNormal", nullptr, StartChildNormal,
783 nullptr, nullptr, nullptr, napi_default, nullptr },
784 { "startChildNoArgs", nullptr, StartChildNoArgs,
785 nullptr, nullptr, nullptr, napi_default, nullptr },
786 { "registerNativeChildExit", nullptr, RegisterNativeChildExit,
787 nullptr, nullptr, nullptr, napi_default, nullptr },
788 { "unregisterNativeChildExit", nullptr, UnregisterNativeChildExit,
789 nullptr, nullptr, nullptr, napi_default, nullptr },
790 { "createThread", nullptr, CreateThread,
791 nullptr, nullptr, nullptr, napi_default, nullptr },
792 { "destroyThread", nullptr, DestroyThread,
793 nullptr, nullptr, nullptr, napi_default, nullptr },
794 { "CreateNativeChildProcessWithConfigs", nullptr, CreateNativeChildProcessWithConfigs,
795 nullptr, nullptr, nullptr, napi_default, nullptr },
796 { "CreateNativeChildProcessWithConfigsLibNamenullptr", nullptr, CreateNativeChildProcessWithConfigsLibNamenullptr,
797 nullptr, nullptr, nullptr, napi_default, nullptr },
798 { "CreateNativeChildProcessWithConfigsNullCallback", nullptr, CreateNativeChildProcessWithConfigsNullCallback,
799 nullptr, nullptr, nullptr, napi_default, nullptr },
800 { "StartNativeChildProcessWithConfigs", nullptr, StartNativeChildProcessWithConfigs,
801 nullptr, nullptr, nullptr, napi_default, nullptr },
802 { "StartNativeChildProcessWithConfigsEntryNull", nullptr, StartNativeChildProcessWithConfigsEntryNull,
803 nullptr, nullptr, nullptr, napi_default, nullptr },
804 { "StartNativeChildProcessWithConfigsFdlistNum17", nullptr, StartNativeChildProcessWithConfigsFdlistNum17,
805 nullptr, nullptr, nullptr, napi_default, nullptr },
806 { "StartNativeChildProcessWithConfigsEntryParams200K", nullptr, StartNativeChildProcessWithConfigsEntryParams200K,
807 nullptr, nullptr, nullptr, napi_default, nullptr },
808 { "SetIsolationModeConfigsNullptr", nullptr, SetIsolationModeConfigsNullptr,
809 nullptr, nullptr, nullptr, napi_default, nullptr },
810 { "SetProcessName", nullptr, SetProcessName,
811 nullptr, nullptr, nullptr, napi_default, nullptr },
812 { "SetProcessNameConfigsNullptr", nullptr, SetProcessNameConfigsNullptr,
813 nullptr, nullptr, nullptr, napi_default, nullptr },
814 { "DestroyChildProcessConfigs", nullptr, DestroyChildProcessConfigs,
815 nullptr, nullptr, nullptr, napi_default, nullptr },
816 { "DestroyChildProcessConfigsNullptr", nullptr, DestroyChildProcessConfigsNullptr,
817 nullptr, nullptr, nullptr, napi_default, nullptr }
818 };
819 napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
820 return exports;
821 }
822 EXTERN_C_END
823
824 static napi_module demoModule = {
825 .nm_version = 1,
826 .nm_flags = 0,
827 .nm_filename = nullptr,
828 .nm_register_func = Init,
829 .nm_modname = "entry",
830 .nm_priv = ((void*)0),
831 .reserved = { 0 },
832 };
833
RegisterEntryModule(void)834 extern "C" __attribute__((constructor)) void RegisterEntryModule(void)
835 {
836 napi_module_register(&demoModule);
837 }
838