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 #ifndef OHOS_ABILITY_RUNTIME_C_NATIVE_CHILD_PROCESS_H
17 #define OHOS_ABILITY_RUNTIME_C_NATIVE_CHILD_PROCESS_H
18 
19 #include "ipc_cparcel.h"
20 
21 /**
22  * @addtogroup ChildProcess
23  * @{
24  *
25  * @brief Provides the APIs to manage child processes.
26  *
27  * @syscap SystemCapability.Ability.AbilityRuntime.Core
28  * @since 12
29  */
30 
31 /**
32  * @file native_child_process.h
33  *
34  * @brief Declares the APIs used to create a native child process and establish an IPC channel between the parent and
35  * child processes.
36  *
37  * @kit AbilityKit
38  * @library libchild_process.so
39  * @syscap SystemCapability.Ability.AbilityRuntime.Core
40  * @since 12
41  */
42 
43 #ifdef __cplusplus
44 extern "C" {
45 #endif
46 
47 /**
48  * @brief Enumerates the error codes used by the native child process module.
49  * @since 12
50  */
51 typedef enum Ability_NativeChildProcess_ErrCode {
52     /**
53      * @error Operation successful.
54      */
55     NCP_NO_ERROR = 0,
56 
57     /**
58      * @error Invalid parameter.
59      */
60     NCP_ERR_INVALID_PARAM = 401,
61 
62     /**
63      * @error Creating a native child process is not supported.
64      */
65     NCP_ERR_NOT_SUPPORTED = 801,
66 
67     /**
68      * @error Internal error.
69      */
70     NCP_ERR_INTERNAL = 16000050,
71 
72     /**
73      * @error A new child process cannot be created during the startup of another native child process.
74      * You can try again after the child process is started.
75      */
76     NCP_ERR_BUSY = 16010001,
77 
78     /**
79      * @error Starting the native child process times out.
80      */
81     NCP_ERR_TIMEOUT = 16010002,
82 
83     /**
84      * @error Server error.
85      */
86     NCP_ERR_SERVICE_ERROR = 16010003,
87 
88     /**
89      * @error The multi-process mode is disabled. A child process cannot be started.
90      */
91     NCP_ERR_MULTI_PROCESS_DISABLED = 16010004,
92 
93     /**
94      * @error A process cannot be created in a child process.
95      */
96     NCP_ERR_ALREADY_IN_CHILD = 16010005,
97 
98     /**
99      * @error The number of native child processes reaches the maximum.
100      */
101     NCP_ERR_MAX_CHILD_PROCESSES_REACHED = 16010006,
102 
103     /**
104      * @error The child process fails to load the dynamic library because the file does not exist
105      * or the corresponding method is not implemented or exported.
106      */
107     NCP_ERR_LIB_LOADING_FAILED = 16010007,
108 
109     /**
110      * @error The child process fails to call the OnConnect method of the dynamic library.
111      * An invalid IPC object pointer may be returned.
112      */
113     NCP_ERR_CONNECTION_FAILED = 16010008,
114 } Ability_NativeChildProcess_ErrCode;
115 
116 
117 /**
118  * @brief Defines a callback function for notifying the child process startup result.
119  *
120  * @param errCode Error code corresponding to the callback function. The following values are available:
121  * {@link NCP_NO_ERROR} if the child process is created successfully.\n
122  * {@link NCP_ERR_LIB_LOADING_FAILED} if loading the dynamic library file fails or the necessary export function
123  * is not implemented in the dynamic library.\n
124  * {@link NCP_ERR_CONNECTION_FAILED} if the OnConnect method implemented in the dynamic library does not return
125  * a valid IPC stub pointer.\n
126  * For details, see {@link Ability_NativeChildProcess_ErrCode}.
127  * @param remoteProxy Pointer to the IPC object of the child process. If an exception occurs, the value may be nullptr.
128  * The object must be released by calling {@link OH_IPCRemoteProxy_Destory} when it is no longer needed.
129  * @see OH_Ability_CreateNativeChildProcess
130  * @see OH_IPCRemoteProxy_Destory
131  * @since 12
132  */
133 typedef void (*OH_Ability_OnNativeChildProcessStarted)(int errCode, OHIPCRemoteProxy *remoteProxy);
134 
135 /**
136  * @brief Creates a child process, loads the specified dynamic library file, and returns the startup result
137  * asynchronously through a callback parameter.
138  * The callback notification is an independent thread. When implementing the callback function,
139  * pay attention to thread synchronization and do not perform time-consuming operations to avoid long-time blocking.
140  *
141  * The dynamic library specified must implement and export the following functions:\n
142  *   1. OHIPCRemoteStub* NativeChildProcess_OnConnect()\n
143  *   2. void NativeChildProcess_MainProc()\n
144  *
145  * The processing logic sequence is shown in the following pseudocode: \n
146  *   Main process: \n
147  *     1. OH_Ability_CreateNativeChildProcess(libName, onProcessStartedCallback)\n
148  *   Child process: \n
149  *     2. dlopen(libName)\n
150  *     3. dlsym("NativeChildProcess_OnConnect")\n
151  *     4. dlsym("NativeChildProcess_MainProc")\n
152  *     5. ipcRemote = NativeChildProcess_OnConnect()\n
153  *     6. NativeChildProcess_MainProc()\n
154  * Main process: \n
155  *     7. onProcessStartedCallback(ipcRemote, errCode)\n
156  * Child process: \n
157  *     8. The child process exits after the NativeChildProcess_MainProc() function is returned. \n
158  *
159  * @param libName Name of the dynamic library file loaded in the child process. The value cannot be nullptr.
160  * @param onProcessStarted Pointer to the callback function for notifying the child process startup result.
161  * The value cannot be nullptr. For details, see {@link OH_Ability_OnNativeChildProcessStarted}.
162  * @return Returns {@link NCP_NO_ERROR} if the call is successful, but the actual startup result is notified by the
163  * callback function.\n
164  * Returns {@link NCP_ERR_INVALID_PARAM} if the dynamic library name or callback function pointer is invalid.\n
165  * Returns {@link NCP_ERR_NOT_SUPPORTED} if the device does not support the creation of native child processes.\n
166  * Returns {@link NCP_ERR_MULTI_PROCESS_DISABLED} if the multi-process mode is disabled on the device.\n
167  * Returns {@link NCP_ERR_ALREADY_IN_CHILD} if it is not allowed to create another child process in the child process.\n
168  * Returns {@link NCP_ERR_MAX_CHILD_PROCESSES_REACHED} if the maximum number of native child processes is reached.\n
169  * For details, see {@link Ability_NativeChildProcess_ErrCode}.
170  * @see OH_Ability_OnNativeChildProcessStarted
171  * @since 12
172  */
173 int OH_Ability_CreateNativeChildProcess(const char* libName,
174                                         OH_Ability_OnNativeChildProcessStarted onProcessStarted);
175 
176 /**
177  * @brief The info of the file descriptors passed to child process.
178  * @since 13
179  */
180 typedef struct NativeChildProcess_Fd {
181     /** the key of the file descriptor. */
182     char* fdName;
183 
184     /** the value of the file descriptor. */
185     int32_t fd;
186 
187     /** the next pointer of the linked list. */
188     struct NativeChildProcess_Fd* next;
189 } NativeChildProcess_Fd;
190 
191 /**
192  * @brief The list of the info of the file descriptors passed to child process.
193  * @since 13
194  */
195 typedef struct NativeChildProcess_FdList {
196     /** the head of the list.
197      * For details, see {@link NativeChildProcess_Fd}.
198      */
199     struct NativeChildProcess_Fd* head;
200 } NativeChildProcess_FdList;
201 
202 /**
203  * @brief Enumerates the isolation modes used by the native child process module.
204  * @since 13
205  */
206 typedef enum NativeChildProcess_IsolationMode {
207     /**
208      * Normal isolation mode, parent process shares the same sandbox or internet with the child process.
209      */
210     NCP_ISOLATION_MODE_NORMAL = 0,
211 
212     /**
213      * Isolated mode, parent process does not share the same sandbox or internet with the child process.
214      */
215     NCP_ISOLATION_MODE_ISOLATED = 1,
216 } NativeChildProcess_IsolationMode;
217 
218 /**
219  * @brief The options used by the child process.
220  * @since 13
221  */
222 typedef struct NativeChildProcess_Options {
223     /** the isolation mode used by the child process.
224      * For details, see {@link NativeChildProcess_IsolationMode}.
225      */
226     NativeChildProcess_IsolationMode isolationMode;
227 
228     /** reserved field for future extension purposes */
229     int64_t reserved;
230 } NativeChildProcess_Options;
231 
232 /**
233  * @brief The arguments passed to the child process.
234  * @since 13
235  */
236 typedef struct NativeChildProcess_Args {
237     /** the entry parameter. */
238     char* entryParams;
239 
240     /** the list of the info of the file descriptors passed to child process.
241      * For details, see {@link NativeChildProcess_FdList}.
242      */
243     struct NativeChildProcess_FdList fdList;
244 } NativeChildProcess_Args;
245 
246 /**
247  * @brief Starts a child process, loads the specified dynamic library file.
248  *
249  * The dynamic library specified must implement a function with NativeChildProcess_Args as a
250  * pamameter(function name can be customized), and export the function, such as:\n
251  *   1. void Main(NativeChildProcess_Args args);
252  *
253  * The processing logic sequence is shown in the following pseudocode: \n
254  *   Main process: \n
255  *     1. OH_Ability_StartNativeChildProcess(entryPoint, args, options)\n
256  *   Child process: \n
257  *     2. dlopen(libName)\n
258  *     3. dlsym("Main")\n
259  *     4. Main(args)\n
260  *     5. The child process exits after the Main(args) function is returned \n
261  *
262  * @param entry Dynamic library and entry function loaded in child process, such as "libEntry.so:Main".
263  * The value cannot be nullptr.
264  * @param args The arguments passed to the child process.
265  * For details, see {@link NativeChildProcess_Args}.
266  * @param options The child process options.
267  * For details, see {@link NativeChildProcess_Options}.
268  * @param pid The started child process id.
269  * @return Returns {@link NCP_NO_ERROR} if the call is successful.\n
270  * Returns {@link NCP_ERR_INVALID_PARAM} if the dynamic library name or callback function pointer is invalid.\n
271  * Returns {@link NCP_ERR_NOT_SUPPORTED} if the device does not support the creation of native child processes.\n
272  * Returns {@link NCP_ERR_ALREADY_IN_CHILD} if it is not allowed to create another child process in the child process.\n
273  * Returns {@link NCP_ERR_MAX_CHILD_PROCESSES_REACHED} if the maximum number of native child processes is reached.\n
274  * For details, see {@link Ability_NativeChildProcess_ErrCode}.
275  * @see OH_Ability_OnNativeChildProcessStarted
276  * @since 13
277  */
278 Ability_NativeChildProcess_ErrCode OH_Ability_StartNativeChildProcess(
279     const char* entry, NativeChildProcess_Args args,
280     NativeChildProcess_Options options, int32_t *pid);
281 
282 #ifdef __cplusplus
283 } // extern "C"
284 #endif
285 
286 /** @} */
287 #endif // OHOS_ABILITY_RUNTIME_C_NATIVE_CHILD_PROCESS_H
288