• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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