• Home
Name Date Size #Lines LOC

..--

communication/broadcast/12-May-2024-646484

config/12-May-2024-105104

figures/12-May-2024-

interfaces/kits/12-May-2024-2,104386

samgr/12-May-2024-3,0252,210

samgr_client/12-May-2024-395319

samgr_endpoint/12-May-2024-3,2282,699

samgr_server/12-May-2024-1,5461,387

BUILD.gnD12-May-20242.1 KiB7164

LICENSED12-May-202410.1 KiB177150

README.mdD12-May-202424.2 KiB640523

README_zh.mdD12-May-202423.1 KiB643524

bundle.jsonD12-May-20241.1 KiB4544

config.gniD12-May-2024945 2219

README.md

1# samgr\_lite<a name="EN-US_TOPIC_0000001081604584"></a>
2
3-   [Introduction](#section11660541593)
4-   [Directory Structure](#section1464106163817)
5-   [Constraints](#section1718733212019)
6-   [Developing a Service](#section159991817144514)
7-   [Developing a Feature of a Service](#section11510542164514)
8-   [Developing an External API for Intra-Process Communication](#section1685211117463)
9-   [Invoking a Service in the Same Process](#section3690162916462)
10-   [Developing an External API for IPC](#section9220246194615)
11-   [Invoking a Service in Another Process](#section114372711475)
12-   [Developing a Client Proxy for Inter-Process Service Invocation](#section09341923114710)
13-   [Repositories Involved](#section10365113863719)
14
15## Introduction<a name="section11660541593"></a>
16
17Due to limited platform resources, a unified system ability \(SA\) framework is provided to harmonize differences of hardware architectures \(for example, RISC-V, Cortex-M, and Cortex-A\), resources, and running modes. Two types of hardware platforms \(M- and A-core\) are defined.
18
19-   M-core: hardware platforms with Cortex-M or equivalent processing capabilities. The system memory is generally less than 512 KB. There is only a lightweight file system that can be used in limited scenarios, or no file system at all. M-core platforms comply with the Cortex Microcontroller Software Interface Standard \(CMSIS\).
20-   A-core: hardware platforms with Cortex-A or equivalent processing capabilities. The system memory is greater than 512 KB. There is a comprehensive file system for storing a large amount of data. A-core platforms comply with the Portable Operating System Interface \(POSIX\) specifications.
21
22This service-oriented SA framework enables you to develop services, features, and external APIs, and implement multi-service process sharing and service invoking for inter-process communication \(IPC\). Wherein:
23
24-   M core provides services, features, external APIs, and multi-service process sharing development.
25-   In addition to the capabilities provided by M-core, A-core provides capabilities such as IPC service invoking, permission control for IPC service invoking, and IPC service API development.
26
27Service-oriented architecture
28
29![](figures/en-us_image_0000001128146921.png)
30
31-   Provider: a service provider that provides capabilities \(external APIs\) for the system
32-   Consumer: a service consumer that invokes the features \(external APIs\) provided by the service
33-   Samgr: an agency that manages capabilities provided by providers and helps consumers discover providers' capabilities
34
35Main objects of the SA framework:
36
37![](figures/en-us_image_0000001081285004.png)
38
39-   SamgrLite: provides service registration and discovery.
40-   Service: implements lifecycle APIs of the service during service development.
41-   Feature: implements lifecycle APIs of the feature during feature development.
42-   IUnknown: implements external APIs for services or features based on  **IUnknown**.
43-   IClientProxy: implements the consumer's proxy to send messages during IPC invoking.
44-   IServerProxy: implements the provider's proxy during IPC invoking, which needs to be implemented by developers.
45
46## Directory Structure<a name="section1464106163817"></a>
47
48**Table  1**  Structure of the source code directory of the SA framework
49
50<a name="table2977131081412"></a>
51<table><thead align="left"><tr id="row7977610131417"><th class="cellrowborder" valign="top" width="31.3%" id="mcps1.2.3.1.1"><p id="p18792459121314"><a name="p18792459121314"></a><a name="p18792459121314"></a>Directory</p>
52</th>
53<th class="cellrowborder" valign="top" width="68.7%" id="mcps1.2.3.1.2"><p id="p77921459191317"><a name="p77921459191317"></a><a name="p77921459191317"></a>Description</p>
54</th>
55</tr>
56</thead>
57<tbody><tr id="row17977171010144"><td class="cellrowborder" valign="top" width="31.3%" headers="mcps1.2.3.1.1 "><p id="p2793159171311"><a name="p2793159171311"></a><a name="p2793159171311"></a>interfaces/kits/samgr_lite/samgr</p>
58</td>
59<td class="cellrowborder" valign="top" width="68.7%" headers="mcps1.2.3.1.2 "><p id="p879375920132"><a name="p879375920132"></a><a name="p879375920132"></a>External APIs of the M- and A-core SA frameworks</p>
60</td>
61</tr>
62<tr id="row6978161091412"><td class="cellrowborder" valign="top" width="31.3%" headers="mcps1.2.3.1.1 "><p id="p37931659101311"><a name="p37931659101311"></a><a name="p37931659101311"></a>interfaces/kits/samgr_lite/registry</p>
63</td>
64<td class="cellrowborder" valign="top" width="68.7%" headers="mcps1.2.3.1.2 "><p id="p6793059171318"><a name="p6793059171318"></a><a name="p6793059171318"></a>External APIs for service invocation between A-core processes</p>
65</td>
66</tr>
67<tr id="row6978201031415"><td class="cellrowborder" valign="top" width="31.3%" headers="mcps1.2.3.1.1 "><p id="p117935599130"><a name="p117935599130"></a><a name="p117935599130"></a>interfaces/kits/samgr_lite/communication/broadcast</p>
68</td>
69<td class="cellrowborder" valign="top" width="68.7%" headers="mcps1.2.3.1.2 "><p id="p0793185971316"><a name="p0793185971316"></a><a name="p0793185971316"></a>External APIs of the event broadcast service within M- and A-core processes</p>
70</td>
71</tr>
72<tr id="row124243183397"><td class="cellrowborder" valign="top" width="31.3%" headers="mcps1.2.3.1.1 "><p id="p104249183396"><a name="p104249183396"></a><a name="p104249183396"></a>services/samgr_lite/samgr/adapter</p>
73</td>
74<td class="cellrowborder" valign="top" width="68.7%" headers="mcps1.2.3.1.2 "><p id="p2424318203914"><a name="p2424318203914"></a><a name="p2424318203914"></a>POSIX and CMSIS interface adaptation layer, which is used to harmonize the differences between the APIs of M- and A-core</p>
75</td>
76</tr>
77<tr id="row1634915717405"><td class="cellrowborder" valign="top" width="31.3%" headers="mcps1.2.3.1.1 "><p id="p193493571406"><a name="p193493571406"></a><a name="p193493571406"></a>services/samgr_lite/samgr/registry</p>
78</td>
79<td class="cellrowborder" valign="top" width="68.7%" headers="mcps1.2.3.1.2 "><p id="p14349257184012"><a name="p14349257184012"></a><a name="p14349257184012"></a>Stub functions for M-core service registration and discovery</p>
80</td>
81</tr>
82<tr id="row1385432741312"><td class="cellrowborder" valign="top" width="31.3%" headers="mcps1.2.3.1.1 "><p id="p1485582714135"><a name="p1485582714135"></a><a name="p1485582714135"></a>services/samgr_lite/samgr/source</p>
83</td>
84<td class="cellrowborder" valign="top" width="68.7%" headers="mcps1.2.3.1.2 "><p id="p085522751319"><a name="p085522751319"></a><a name="p085522751319"></a>Basic code for the M- and A-core SA frameworks</p>
85</td>
86</tr>
87<tr id="row7968155877"><td class="cellrowborder" valign="top" width="31.3%" headers="mcps1.2.3.1.1 "><p id="p89681851717"><a name="p89681851717"></a><a name="p89681851717"></a>services/samgr_lite/samgr_client</p>
88</td>
89<td class="cellrowborder" valign="top" width="68.7%" headers="mcps1.2.3.1.2 "><p id="p169681051873"><a name="p169681051873"></a><a name="p169681051873"></a>Registration and discovery for service invocation between A-core processes</p>
90</td>
91</tr>
92<tr id="row18291912179"><td class="cellrowborder" valign="top" width="31.3%" headers="mcps1.2.3.1.1 "><p id="p1729111214715"><a name="p1729111214715"></a><a name="p1729111214715"></a>services/samgr_lite/samgr_server</p>
93</td>
94<td class="cellrowborder" valign="top" width="68.7%" headers="mcps1.2.3.1.2 "><p id="p7839893352"><a name="p7839893352"></a><a name="p7839893352"></a>IPC address management and access control for service invocation between A-core processes</p>
95</td>
96</tr>
97<tr id="row6971514279"><td class="cellrowborder" valign="top" width="31.3%" headers="mcps1.2.3.1.1 "><p id="p1797118141671"><a name="p1797118141671"></a><a name="p1797118141671"></a>services/samgr_lite/samgr_endpoint</p>
98</td>
99<td class="cellrowborder" valign="top" width="68.7%" headers="mcps1.2.3.1.2 "><p id="p597119145716"><a name="p597119145716"></a><a name="p597119145716"></a>Packet RX/TX management for A-core IPC</p>
100</td>
101</tr>
102<tr id="row33121991272"><td class="cellrowborder" valign="top" width="31.3%" headers="mcps1.2.3.1.1 "><p id="p143121991875"><a name="p143121991875"></a><a name="p143121991875"></a>services/samgr_lite/communication/broadcast</p>
103</td>
104<td class="cellrowborder" valign="top" width="68.7%" headers="mcps1.2.3.1.2 "><p id="p16312169179"><a name="p16312169179"></a><a name="p16312169179"></a>Event broadcast service for M- and A-core processes</p>
105</td>
106</tr>
107</tbody>
108</table>
109
110## Constraints<a name="section1718733212019"></a>
111
112-   The SA framework is developed using the C programming language.
113-   Services in the same process use  **IUnknown**  for invoking. Messages are passed to the service through  **IUnknown**.
114-   The service name and feature name must be constant character strings and the length must be less than 16 bytes.
115-   More-core depends on the Bootstrap service and calls the  **OHOS\_SystemInit\(\)**  function in the system startup function.
116-   A-core depends on the Samgr library and calls the  **SAMGR\_Bootstrap\(\)**  function in the  **main**  function.
117
118## Developing a Service<a name="section159991817144514"></a>
119
120-   Inherit and redefine a service.
121
122    ```
123    typedef struct ExampleService {
124        INHERIT_SERVICE;
125        INHERIT_IUNKNOWNENTRY(DefaultFeatureApi);
126        Identity identity;
127    } ExampleService;
128    ```
129
130-   Implement the lifecycle function of the service.
131
132    ```
133    static const char *GetName(Service *service)
134    {
135        return EXAMPLE_SERVICE;
136    }
137
138    static BOOL Initialize(Service *service, Identity identity)
139    {
140        ExampleService *example = (ExampleService *)service;
141        // Save the unique ID of the service, which is used when IUnknown is used to send messages to the service.
142        example->identity = identity;
143        return TRUE;
144    }
145    static BOOL MessageHandle(Service *service, Request *msg)
146    {
147        ExampleService *example = (ExampleService *)service;
148        switch (msg->msgId) {
149            case MSG_SYNC:
150                // Process the service.
151                break;
152            default:break;
153        }
154        return FALSE;
155    }
156    static TaskConfig GetTaskConfig(Service *service)
157    {
158        TaskConfig config = {LEVEL_HIGH, PRI_BELOW_NORMAL,
159                             0x800, 20, SHARED_TASK};
160        return config;
161    }
162    ```
163
164-   Create a service object.
165
166    ```
167    static ExampleService g_example = {
168        .GetName = GetName,
169        .Initialize = Initialize,
170        .MessageHandle = MessageHandle,
171        .GetTaskConfig = GetTaskConfig,
172        SERVER_IPROXY_IMPL_BEGIN,
173            .Invoke = NULL,
174            .SyncCall = SyncCall,
175        IPROXY_END,
176    };
177    ```
178
179-   Register the service and API with Samgr.
180
181    ```
182    static void Init(void)
183    {
184        SAMGR_GetInstance()->RegisterService((Service *)&g_example);
185        SAMGR_GetInstance()->RegisterDefaultFeatureApi(EXAMPLE_SERVICE, GET_IUNKNOWN(g_example));
186    }
187    ```
188
189-   Define the initializer of the service.
190
191    ```
192    SYSEX_SERVICE_INIT(Init);
193
194    ```
195
196
197## Developing a Feature of a Service<a name="section11510542164514"></a>
198
199-   Inherit and redefine a feature.
200
201    ```
202    typedef struct DemoFeature {
203        INHERIT_FEATURE;
204        INHERIT_IUNKNOWNENTRY(DemoApi);
205        Identity identity;
206        Service *parent;
207    } DemoFeature;
208    ```
209
210-   Implement the lifecycle function of the feature.
211
212    ```
213    static const char *FEATURE_GetName(Feature *feature)
214    {
215        return EXAMPLE_FEATURE;
216    }
217
218    static void FEATURE_OnInitialize(Feature *feature, Service *parent, Identity identity)
219    {
220        DemoFeature *demoFeature = (DemoFeature *)feature;
221        demoFeature->identity = identity;
222        demoFeature->parent = parent;
223    }
224
225    static void FEATURE_OnStop(Feature *feature, Identity identity)
226    {
227        g_example.identity.queueId = NULL;
228        g_example.identity.featureId = -1;
229        g_example.identity.serviceId = -1;
230    }
231
232    static BOOL FEATURE_OnMessage(Feature *feature, Request *request)
233    {
234        if (request->msgId == MSG_PROC) {
235            Response response = {.data = "Yes, you did!", .len = 0};
236            SAMGR_SendResponse(request, &response);
237            return TRUE;
238        } else {
239            if (request->msgId == MSG_TIME_PROC) {
240                LOS_Msleep(WAIT_FEATURE_PROC * 10);
241                if (request->msgValue) {
242                    SAMGR_PrintServices();
243                } else {
244                    SAMGR_PrintOperations();
245                }
246                AsyncTimeCall(GET_IUNKNOWN(g_example));
247                return FALSE;
248            }
249        }
250        return FALSE;
251    }
252    ```
253
254-   Create a feature object.
255
256    ```
257    static DemoFeature g_example = {
258        .GetName = FEATURE_GetName,
259        .OnInitialize = FEATURE_OnInitialize,
260        .OnStop = FEATURE_OnStop,
261        .OnMessage = FEATURE_OnMessage,
262        DEFAULT_IUNKNOWN_ENTRY_BEGIN,
263            .AsyncCall = AsyncCall,
264            .AsyncTimeCall = AsyncTimeCall,
265            .SyncCall = SyncCall,
266            .AsyncCallBack = AsyncCallBack,
267        DEFAULT_IUNKNOWN_ENTRY_END,
268        .identity = {-1, -1, NULL},
269    };
270    ```
271
272-   Register the feature and API with Samgr.
273
274    ```
275    static void Init(void){
276        SAMGR_GetInstance()->RegisterFeature(EXAMPLE_SERVICE, (Feature *)&g_example);
277        SAMGR_GetInstance()->RegisterFeatureApi(EXAMPLE_SERVICE, EXAMPLE_FEATURE, GET_IUNKNOWN(g_example));
278    }
279    ```
280
281-   Define the initializer of the feature.
282
283    ```
284    SYSEX_FEATURE_INIT(Init);
285
286    ```
287
288
289## Developing an External API for Intra-Process Communication<a name="section1685211117463"></a>
290
291-   Define the  **IUnknown**  API.
292
293    ```
294    typedef struct DemoApi {
295        INHERIT_IUNKNOWN;
296        BOOL (*AsyncCall)(IUnknown *iUnknown, const char *buff);
297        BOOL (*AsyncTimeCall)(IUnknown *iUnknown);
298        BOOL (*SyncCall)(IUnknown *iUnknown, struct Payload *payload);
299        BOOL (*AsyncCallBack)(IUnknown *iUnknown, const char *buff, Handler handler);
300    } DemoApi;
301    ```
302
303-   Define the reference object of  **IUnknown**.
304
305    ```
306    typedef struct DemoRefApi {
307        INHERIT_IUNKNOWNENTRY(DemoApi);
308    } DemoRefApi;
309    ```
310
311-   Initialize the object of  **IUnknown**.
312
313    ```
314    static DemoRefApi api = {
315        DEFAULT_IUNKNOWN_ENTRY_BEGIN,
316            .AsyncCall = AsyncCall,
317            .AsyncTimeCall = AsyncTimeCall,
318            .SyncCall = SyncCall,
319            .AsyncCallBack = AsyncCallBack,
320        DEFAULT_IUNKNOWN_ENTRY_END,
321    };
322    ```
323
324-   Register the feature API.
325
326    ```
327    SAMGR_GetInstance()->RegisterFeatureApi(EXAMPLE_SERVICE, EXAMPLE_FEATURE, GET_IUNKNOWN(api));
328
329    ```
330
331
332## Invoking a Service in the Same Process<a name="section3690162916462"></a>
333
334-   Obtain the external API of the service.
335
336    ```
337    DemoApi *demoApi = NULL;
338    IUnknown *iUnknown = SAMGR_GetInstance()->GetFeatureApi(EXAMPLE_SERVICE, EXAMPLE_FEATURE);
339    if (iUnknown == NULL) {
340        return NULL;
341    }
342    int result = iUnknown->QueryInterface(iUnknown, DEFAULT_VERSION, (void **)&demoApi);
343    if (result != 0 || demoApi == NULL) {
344        return NULL;
345    }
346    ```
347
348-   Call the API.
349
350    ```
351    if (demoApi->AsyncCallBack == NULL) {
352        return NULL;
353    }
354    demoApi->AsyncCallBack((IUnknown *)demoApi, "I wanna async call callback good result!", AsyncHandler);
355    ```
356
357-   Release the API.
358
359    ```
360    int32 ref = demoApi->Release((IUnknown *)demoApi);
361
362    ```
363
364
365## Developing an External API for IPC<a name="section9220246194615"></a>
366
367-   Inherit  **IServerProxy**  to replace  **IUnknown**: INHERIT\_SERVER\_IPROXY
368
369    ```
370    typedef struct DemoFeatureApi {
371        INHERIT_SERVER_IPROXY;
372        BOOL (*AsyncCall)(IUnknown *iUnknown, const char *buff);
373        BOOL (*AsyncTimeCall)(IUnknown *iUnknown);
374        BOOL (*SyncCall)(IUnknown *iUnknown, struct Payload *payload);
375        BOOL (*AsyncCallBack)(IUnknown *iUnknown, const char *buff, IOwner notify, INotifyFunc handler);
376    } DemoFeatureApi;
377    ```
378
379-   Initialize the  **IServerProxy**  object.
380
381    ```
382    static DemoFeature g_example = {
383        SERVER_IPROXY_IMPL_BEGIN,
384        .Invoke = Invoke,
385        .AsyncCall = AsyncCall,
386        .AsyncTimeCall = AsyncTimeCall,
387        .SyncCall = SyncCall,
388        .AsyncCallBack = AsyncCallBack,
389        IPROXY_END,
390    };
391    ```
392
393-   Implement the  **Invoke**  function to process IPC messages.
394
395    ```
396    static int32 Invoke(IServerProxy *iProxy, int funcId, void *origin, IpcIo *req, IpcIo *reply)
397    {
398        DemoFeatureApi *api = (DemoFeatureApi *)iProxy;
399        BOOL ret;
400        size_t len = 0;
401        switch (funcId) {
402            case ID_ASYNCALL:
403                ret = api->AsyncCall((IUnknown *)iProxy, (char *)IpcIoPopString(req, &len));
404                IpcIoPushBool(reply, ret);
405                break;
406            case ID_ASYNTIMECALL:
407                ret = api->AsyncTimeCall((IUnknown *)iProxy);
408                IpcIoPushBool(reply, ret);
409                break;
410            case ID_SYNCCALL: {
411                struct Payload payload;
412                payload.id = IpcIoPopInt32(req);
413                payload.value = IpcIoPopInt32(req);
414                payload.name = (char *)IpcIoPopString(req, &len);
415                ret = api->SyncCall((IUnknown *)iProxy, &payload);
416                IpcIoPushString(reply, ret ? "TRUE" : "FALSE");
417            }
418                break;
419            case ID_ASYNCCALLBACK: { // convert to sync proxy
420                IpcIoPushString(reply, "Yes, you did!");
421                IpcIoPushBool(reply, TRUE);
422            }
423                break;
424            default:
425                IpcIoPushBool(reply, FALSE);
426                break;
427        }
428        return EC_SUCCESS;
429    }
430    ```
431
432-   Register the API. This step is same as the API registration for intra-process communication.
433
434    ```
435    SAMGR_GetInstance()->RegisterFeatureApi(EXAMPLE_SERVICE, EXAMPLE_FEATURE, GET_IUNKNOWN(g_example));
436
437    ```
438
439
440## Invoking a Service in Another Process<a name="section114372711475"></a>
441
442-   Obtain the external API of the service in another process.
443
444    ```
445    IClientProxy *demoApi = NULL;
446    IUnknown *iUnknown = SAMGR_GetInstance()->GetFeatureApi(EXAMPLE_SERVICE, EXAMPLE_FEATURE);
447    if (iUnknown == NULL) {
448        return NULL;
449    }
450    int result = iUnknown->QueryInterface(iUnknown, CLIENT_PROXY_VER, (void **)&demoApi);
451    if (result != 0 || demoApi == NULL) {
452        return NULL;
453    }
454    ```
455
456-   Invoke the API for sending IPC messages.
457
458    ```
459    IpcIo request;char data[250];
460    IpcIoInit(&request, data, sizeof(data), 0);
461    demoApi->Invoke(demoApi, 0, &request, NULL, NULL);
462    ```
463
464-   Release the API.
465
466    ```
467    int32 ref = demoApi->Release((IUnknown *)demoApi);
468
469    ```
470
471
472## Developing a Client Proxy for Inter-Process Service Invocation<a name="section09341923114710"></a>
473
474-   Define a client proxy for the IPC API.
475
476    ```
477    typedef struct DemoClientProxy {
478        INHERIT_CLIENT_IPROXY;
479        BOOL (*AsyncCall)(IUnknown *iUnknown, const char *buff);
480        BOOL (*AsyncTimeCall)(IUnknown *iUnknown);
481        BOOL (*SyncCall)(IUnknown *iUnknown, struct Payload *payload);
482        BOOL (*AsyncCallBack)(IUnknown *iUnknown, const char *buff, IOwner notify, INotifyFunc handler);
483    } DemoClientProxy;
484    typedef struct DemoClientEntry {
485        INHERIT_IUNKNOWNENTRY(DemoClientProxy);
486    } DemoClientEntry;
487    ```
488
489-   Enable the client proxy to encapsulate the IPC message API.
490
491    ```
492    static BOOL AsyncCall(IUnknown *iUnknown, const char *buff)
493    {
494        DemoClientProxy *proxy = (DemoClientProxy *)iUnknown;
495        IpcIo request;
496        char data[MAX_DATA_LEN];
497        IpcIoInit(&request, data, MAX_DATA_LEN, 0);
498        IpcIoPushString(&request, buff);
499        int ret = proxy->Invoke((IClientProxy *)proxy, ID_ASYNCALL, &request, NULL, NULL);
500        return ret == EC_SUCCESS;
501    }
502
503    static BOOL AsyncTimeCall(IUnknown *iUnknown)
504    {
505        DemoClientProxy *proxy = (DemoClientProxy *)iUnknown;
506        IpcIo request;
507        char data[MAX_DATA_LEN];
508        IpcIoInit(&request, data, MAX_DATA_LEN, 0);
509        int ret = proxy->Invoke((IClientProxy *)proxy, ID_ASYNTIMECALL, &request, NULL, NULL);
510        return ret == EC_SUCCESS;
511    }
512
513    static int Callback(IOwner owner, int code, IpcIo *reply)
514    {
515        size_t len = 0;
516        return strcpy_s(owner, MAX_DATA_LEN, (char *)IpcIoPopString(reply, &len));
517    }
518
519    static BOOL SyncCall(IUnknown *iUnknown, struct Payload *payload)
520    {
521        DemoClientProxy *proxy = (DemoClientProxy *)iUnknown;
522        IpcIo request;
523        char data[MAX_DATA_LEN];
524        IpcIoInit(&request, data, MAX_DATA_LEN, 0);
525        IpcIoPushInt32(&request, payload->id);
526        IpcIoPushInt32(&request, payload->value);
527        IpcIoPushString(&request, payload->name);
528        int ret = proxy->Invoke((IClientProxy *)proxy, ID_SYNCCALL, &request, data, Callback);
529        data[MAX_DATA_LEN - 1] = 0;
530        HILOG_INFO(HILOG_MODULE_APP, "[TID:0x%lx]Remote response is %s!", pthread_self(), data);
531        return ret == EC_SUCCESS;
532    }
533
534    struct CurrentNotify {
535        IOwner notify;
536        INotifyFunc handler;
537    };
538
539    static int CurrentCallback(IOwner owner, int code, IpcIo *reply)
540    {
541        struct CurrentNotify *notify = (struct CurrentNotify *)owner;
542        size_t len = 0;
543        char *response = (char *)IpcIoPopString(reply, &len);
544        HILOG_INFO(HILOG_MODULE_APP, "[TID:0x%lx]Notify Remote response is %s!", pthread_self(), response);
545        notify->handler(notify->notify, response);
546        return EC_SUCCESS;
547    }
548
549    static BOOL AsyncCallBack(IUnknown *iUnknown, const char *buff, IOwner notify, INotifyFunc handler)
550    {
551        struct CurrentNotify owner = {notify, handler};
552        DemoClientProxy *proxy = (DemoClientProxy *)iUnknown;
553        IpcIo request;
554        char data[MAX_DATA_LEN];
555        IpcIoInit(&request, data, MAX_DATA_LEN, 0);
556        IpcIoPushString(&request, buff);
557        int ret = proxy->Invoke((IClientProxy *)proxy, ID_ASYNCCALLBACK, &request, &owner, CurrentCallback);
558        return ret == EC_SUCCESS;
559    }
560    ```
561
562-   Implement the factory method for creating the client proxy.
563
564    ```
565    void *DEMO_CreatClient(const char *service, const char *feature, uint32 size)
566    {
567        (void)service;
568        (void)feature;
569        uint32 len = size + sizeof(DemoClientEntry);
570        uint8 *client = malloc(len);
571        (void)memset_s(client, len, 0, len);
572        DemoClientEntry *entry = (DemoClientEntry *)&client[size];
573        entry->ver = ((uint16)CLIENT_PROXY_VER | (uint16)DEFAULT_VERSION);
574        entry->ref = 1;
575        entry->iUnknown.QueryInterface = IUNKNOWN_QueryInterface;
576        entry->iUnknown.AddRef = IUNKNOWN_AddRef;
577        entry->iUnknown.Release = IUNKNOWN_Release;
578        entry->iUnknown.Invoke = NULL;
579        entry->iUnknown.AsyncCall = AsyncCall;
580        entry->iUnknown.AsyncTimeCall = AsyncTimeCall;
581        entry->iUnknown.SyncCall = SyncCall;
582        entry->iUnknown.AsyncCallBack = AsyncCallBack;
583        return client;
584    }
585    void DEMO_DestroyClient(const char *service, const char *feature, void *iproxy)
586    {
587        free(iproxy);
588    }
589    ```
590
591-   Register the factory method of the client proxy with Samgr.
592
593    ```
594    SAMGR_RegisterFactory(EXAMPLE_SERVICE, EXAMPLE_FEATURE, DEMO_CreatClient, DEMO_DestroyClient);
595    ```
596
597-   Obtain the external API of the service in another process.
598
599    ```
600    DemoClientProxy *demoApi = NULL;
601    IUnknown *iUnknown = SAMGR_GetInstance()->GetFeatureApi(EXAMPLE_SERVICE, EXAMPLE_FEATURE);
602    if (iUnknown == NULL) {
603        return NULL;
604    }
605    int result = iUnknown->QueryInterface(iUnknown, DEFAULT_VERSION, (void **)&demoApi);
606    if (result != 0 || demoApi == NULL) {
607        return NULL;
608    }
609    ```
610
611-   Invoke the client proxy API of the service in another process.
612
613    ```
614    if (demoApi->AsyncCallBack == NULL) {
615        return NULL;
616    }
617    demoApi->AsyncCallBack((IUnknown *)demoApi,
618                           "I wanna async call callback good result!", NULL, AsyncHandler);
619    ```
620
621-   Release the API.
622
623    ```
624    int32 ref = demoApi->Release((IUnknown *)demoApi);
625    ```
626
627
628## Repositories Involved<a name="section10365113863719"></a>
629
630System Ability Management Subsystem
631
632[**systemabilitymgr\_samgr\_lite**](https://gitee.com/openharmony/systemabilitymgr_samgr_lite)
633
634[systemabilitymgr\_samgr](https://gitee.com/openharmony/systemabilitymgr_samgr)
635
636[systemabilitymgr\_safwk](https://gitee.com/openharmony/systemabilitymgr_safwk)
637
638[systemabilitymgr\_safwk\_lite](https://gitee.com/openharmony/systemabilitymgr_safwk_lite)
639
640

README_zh.md

1# 轻量型系统服务管理部件<a name="ZH-CN_TOPIC_0000001081604584"></a>
2
3-   [简介](#section11660541593)
4-   [目录](#section1464106163817)
5-   [约束](#section1718733212019)
6-   [开发服务](#section159991817144514)
7-   [开发服务的子功能](#section11510542164514)
8-   [开发进程内对外接口](#section1685211117463)
9-   [调用进程内服务](#section3690162916462)
10-   [开发跨进程间对外接口](#section9220246194615)
11-   [调用跨进程间服务](#section114372711475)
12-   [开发跨进程间服务调用客户端代理](#section09341923114710)
13-   [相关仓](#section10365113863719)
14
15## 简介<a name="section11660541593"></a>
16
17由于平台资源有限,且硬件平台多样,因此需要屏蔽不同硬件架构和平台资源的不同、以及运行形态的不同,提供统一化的系统服务开发框架。根据RISC-V、Cortex-M、Cortex-A不同硬件平台,分为两种硬件平台,以下简称M核、A核。
18
19-   M核:处理器架构为Cortex-M或同等处理能力的硬件平台,系统内存一般低于512KB,无文件系统或者仅提供一个可有限使用的轻量级文件系统,遵循CMSIS接口规范。
20-   A核:处理器架构为Cortex-A或同等处理能力的硬件平台,内存资源大于512KB,文件系统完善,可存储大量数据,遵循POSIX接口规范。
21
22系统服务框架基于面向服务的架构,提供了服务开发、服务的子功能开发、对外接口的开发、以及多服务共进程、进程间服务调用等开发能力。其中:
23
24-   M核:包含服务开发、服务的子功能开发、对外接口的开发以及多服务共进程的开发框架。
25-   A核:在M核能力基础之上,包含了进程间服务调用、进程间服务调用权限控制、进程间服务接口的开发等能力。
26
27## 系统架构<a name="section342962219551"></a>
28
29**图 1**  面向服务的架构
30
31
32![](figures/zh-cn_image_0000001128146921.png)
33
34-   Provider:服务的提供者,为系统提供能力(对外接口)。
35-   Consumer:服务的消费者,调用服务提供的功能(对外接口)。
36-   Samgr:作为中介者,管理Provider提供的能力,同时帮助Consumer发现Provider的能力。
37
38**图 2**  系统服务开发框架主体对象:
39
40![](figures/zh-cn_image_0000001081285004.png)
41
42-   SamgrLite:主要提供服务的注册与发现能力。
43-   Service:开发服务时,需要实现的服务的生命周期接口。
44-   Feature:开发功能时,需要实现的功能的生命周期接口。
45-   IUnknown:基于IUnknown开发服务或功能的对外接口。
46-   IClientProxy:IPC调用时,消费者的消息发送代理。
47-   IServerProxy:IPC调用时,开发者需要实现提供者的消息处理接口。
48
49## 目录<a name="section1464106163817"></a>
50
51**表 1**  系统服务框架源代码目录结构
52
53<a name="table2977131081412"></a>
54<table><thead align="left"><tr id="row7977610131417"><th class="cellrowborder" valign="top" width="31.3%" id="mcps1.2.3.1.1"><p id="p18792459121314"><a name="p18792459121314"></a><a name="p18792459121314"></a>名称</p>
55</th>
56<th class="cellrowborder" valign="top" width="68.7%" id="mcps1.2.3.1.2"><p id="p77921459191317"><a name="p77921459191317"></a><a name="p77921459191317"></a>描述</p>
57</th>
58</tr>
59</thead>
60<tbody><tr id="row17977171010144"><td class="cellrowborder" valign="top" width="31.3%" headers="mcps1.2.3.1.1 "><p id="p2793159171311"><a name="p2793159171311"></a><a name="p2793159171311"></a>interfaces/kits/samgr_lite/samgr</p>
61</td>
62<td class="cellrowborder" valign="top" width="68.7%" headers="mcps1.2.3.1.2 "><p id="p879375920132"><a name="p879375920132"></a><a name="p879375920132"></a>M核和A核系统服务框架对外接口定义。</p>
63</td>
64</tr>
65<tr id="row6978161091412"><td class="cellrowborder" valign="top" width="31.3%" headers="mcps1.2.3.1.1 "><p id="p37931659101311"><a name="p37931659101311"></a><a name="p37931659101311"></a>interfaces/kits/samgr_lite/registry</p>
66</td>
67<td class="cellrowborder" valign="top" width="68.7%" headers="mcps1.2.3.1.2 "><p id="p6793059171318"><a name="p6793059171318"></a><a name="p6793059171318"></a>A核进程间服务调用的对外接口定义。</p>
68</td>
69</tr>
70<tr id="row6978201031415"><td class="cellrowborder" valign="top" width="31.3%" headers="mcps1.2.3.1.1 "><p id="p117935599130"><a name="p117935599130"></a><a name="p117935599130"></a>interfaces/kits/samgr_lite/communication/broadcast</p>
71</td>
72<td class="cellrowborder" valign="top" width="68.7%" headers="mcps1.2.3.1.2 "><p id="p0793185971316"><a name="p0793185971316"></a><a name="p0793185971316"></a>M核和A核进程内事件广播服务的对外接口定义。</p>
73</td>
74</tr>
75<tr id="row124243183397"><td class="cellrowborder" valign="top" width="31.3%" headers="mcps1.2.3.1.1 "><p id="p104249183396"><a name="p104249183396"></a><a name="p104249183396"></a>services/samgr_lite/samgr/adapter</p>
76</td>
77<td class="cellrowborder" valign="top" width="68.7%" headers="mcps1.2.3.1.2 "><p id="p2424318203914"><a name="p2424318203914"></a><a name="p2424318203914"></a>POSIX和CMSIS接口适配层来屏蔽A核M核接口差异。</p>
78</td>
79</tr>
80<tr id="row1634915717405"><td class="cellrowborder" valign="top" width="31.3%" headers="mcps1.2.3.1.1 "><p id="p193493571406"><a name="p193493571406"></a><a name="p193493571406"></a>services/samgr_lite/samgr/registry</p>
81</td>
82<td class="cellrowborder" valign="top" width="68.7%" headers="mcps1.2.3.1.2 "><p id="p14349257184012"><a name="p14349257184012"></a><a name="p14349257184012"></a>M核服务注册发现的桩函数。</p>
83</td>
84</tr>
85<tr id="row1385432741312"><td class="cellrowborder" valign="top" width="31.3%" headers="mcps1.2.3.1.1 "><p id="p1485582714135"><a name="p1485582714135"></a><a name="p1485582714135"></a>services/samgr_lite/samgr/source</p>
86</td>
87<td class="cellrowborder" valign="top" width="68.7%" headers="mcps1.2.3.1.2 "><p id="p085522751319"><a name="p085522751319"></a><a name="p085522751319"></a>M核和A核系统服务开发框架基础代码。</p>
88</td>
89</tr>
90<tr id="row7968155877"><td class="cellrowborder" valign="top" width="31.3%" headers="mcps1.2.3.1.1 "><p id="p89681851717"><a name="p89681851717"></a><a name="p89681851717"></a>services/samgr_lite/samgr_client</p>
91</td>
92<td class="cellrowborder" valign="top" width="68.7%" headers="mcps1.2.3.1.2 "><p id="p169681051873"><a name="p169681051873"></a><a name="p169681051873"></a>A核进程间服务调用的注册与发现。</p>
93</td>
94</tr>
95<tr id="row18291912179"><td class="cellrowborder" valign="top" width="31.3%" headers="mcps1.2.3.1.1 "><p id="p1729111214715"><a name="p1729111214715"></a><a name="p1729111214715"></a>services/samgr_lite/samgr_server</p>
96</td>
97<td class="cellrowborder" valign="top" width="68.7%" headers="mcps1.2.3.1.2 "><p id="p7839893352"><a name="p7839893352"></a><a name="p7839893352"></a>A核进程间服务调用的IPC地址管理和访问控制。</p>
98</td>
99</tr>
100<tr id="row6971514279"><td class="cellrowborder" valign="top" width="31.3%" headers="mcps1.2.3.1.1 "><p id="p1797118141671"><a name="p1797118141671"></a><a name="p1797118141671"></a>services/samgr_lite/samgr_endpoint</p>
101</td>
102<td class="cellrowborder" valign="top" width="68.7%" headers="mcps1.2.3.1.2 "><p id="p597119145716"><a name="p597119145716"></a><a name="p597119145716"></a>A核IPC通信消息收发包管理。</p>
103</td>
104</tr>
105<tr id="row33121991272"><td class="cellrowborder" valign="top" width="31.3%" headers="mcps1.2.3.1.1 "><p id="p143121991875"><a name="p143121991875"></a><a name="p143121991875"></a>services/samgr_lite/communication/broadcast</p>
106</td>
107<td class="cellrowborder" valign="top" width="68.7%" headers="mcps1.2.3.1.2 "><p id="p16312169179"><a name="p16312169179"></a><a name="p16312169179"></a>M核和A核进程内事件广播服务。</p>
108</td>
109</tr>
110</tbody>
111</table>
112
113## 约束<a name="section1718733212019"></a>
114
115-   系统服务开发框架统一使用C开发。
116-   同进程内服务间调用统一使用IUnknown接口对外象,消息接口统一由IUnknown接口传递给本服务。
117-   服务名和功能名必需使用常量字符串且长度小于16个字节。
118-   M核:系统依赖上bootstrap服务,在系统启动函数中调用OHOS\_SystemInit\(\)函数。
119-   A核:系统依赖samgr库,在main函数中调用SAMGR\_Bootstrap\(\)函数。
120
121## 开发服务<a name="section159991817144514"></a>
122
123-   继承并重新定义服务:
124
125    ```
126    typedef struct ExampleService {
127        INHERIT_SERVICE;
128        INHERIT_IUNKNOWNENTRY(DefaultFeatureApi);
129        Identity identity;
130    } ExampleService;
131    ```
132
133-   实现服务的生命周期函数:
134
135    ```
136    static const char *GetName(Service *service)
137    {
138        return EXAMPLE_SERVICE;
139    }
140
141    static BOOL Initialize(Service *service, Identity identity)
142    {
143        ExampleService *example = (ExampleService *)service;
144        // 保存服务的唯一身份标识,用来自己的IUnknown接口对服务发消息时使用。
145        example->identity = identity;
146        return TRUE;
147    }
148    static BOOL MessageHandle(Service *service, Request *msg)
149    {
150        ExampleService *example = (ExampleService *)service;
151        switch (msg->msgId) {
152            case MSG_SYNC:
153                // 业务处理
154                break;
155            default:break;
156        }
157        return FALSE;
158    }
159    static TaskConfig GetTaskConfig(Service *service)
160    {
161        TaskConfig config = {LEVEL_HIGH, PRI_BELOW_NORMAL,
162                             0x800, 20, SHARED_TASK};
163        return config;
164    }
165    ```
166
167-   创建服务对象:
168
169    ```
170    static ExampleService g_example = {
171        .GetName = GetName,
172        .Initialize = Initialize,
173        .MessageHandle = MessageHandle,
174        .GetTaskConfig = GetTaskConfig,
175        SERVER_IPROXY_IMPL_BEGIN,
176            .Invoke = NULL,
177            .SyncCall = SyncCall,
178        IPROXY_END,
179    };
180    ```
181
182-   向SAMGR注册服务及接口:
183
184    ```
185    static void Init(void)
186    {
187        SAMGR_GetInstance()->RegisterService((Service *)&g_example);
188        SAMGR_GetInstance()->RegisterDefaultFeatureApi(EXAMPLE_SERVICE, GET_IUNKNOWN(g_example));
189    }
190    ```
191
192-   定义服务的初始化入口:
193
194    ```
195    SYSEX_SERVICE_INIT(Init);
196
197    ```
198
199
200## 开发服务的子功能<a name="section11510542164514"></a>
201
202-   继承并重新定义功能:
203
204    ```
205    typedef struct DemoFeature {
206        INHERIT_FEATURE;
207        INHERIT_IUNKNOWNENTRY(DemoApi);
208        Identity identity;
209        Service *parent;
210    } DemoFeature;
211    ```
212
213-   实现功能的生命周期函数:
214
215    ```
216    static const char *FEATURE_GetName(Feature *feature)
217    {
218        return EXAMPLE_FEATURE;
219    }
220
221    static void FEATURE_OnInitialize(Feature *feature, Service *parent, Identity identity)
222    {
223        DemoFeature *demoFeature = (DemoFeature *)feature;
224        demoFeature->identity = identity;
225        demoFeature->parent = parent;
226    }
227
228    static void FEATURE_OnStop(Feature *feature, Identity identity)
229    {
230        g_example.identity.queueId = NULL;
231        g_example.identity.featureId = -1;
232        g_example.identity.serviceId = -1;
233    }
234
235    static BOOL FEATURE_OnMessage(Feature *feature, Request *request)
236    {
237        if (request->msgId == MSG_PROC) {
238            Response response = {.data = "Yes, you did!", .len = 0};
239            SAMGR_SendResponse(request, &response);
240            return TRUE;
241        } else {
242            if (request->msgId == MSG_TIME_PROC) {
243                LOS_Msleep(WAIT_FEATURE_PROC * 10);
244                if (request->msgValue) {
245                    SAMGR_PrintServices();
246                } else {
247                    SAMGR_PrintOperations();
248                }
249                AsyncTimeCall(GET_IUNKNOWN(g_example));
250                return FALSE;
251            }
252        }
253        return FALSE;
254    }
255    ```
256
257-   创建功能对象:
258
259    ```
260    static DemoFeature g_example = {
261        .GetName = FEATURE_GetName,
262        .OnInitialize = FEATURE_OnInitialize,
263        .OnStop = FEATURE_OnStop,
264        .OnMessage = FEATURE_OnMessage,
265        DEFAULT_IUNKNOWN_ENTRY_BEGIN,
266            .AsyncCall = AsyncCall,
267            .AsyncTimeCall = AsyncTimeCall,
268            .SyncCall = SyncCall,
269            .AsyncCallBack = AsyncCallBack,
270        DEFAULT_IUNKNOWN_ENTRY_END,
271        .identity = {-1, -1, NULL},
272    };
273    ```
274
275-   向SAMGR注册功能及接口:
276
277    ```
278    static void Init(void){
279        SAMGR_GetInstance()->RegisterFeature(EXAMPLE_SERVICE, (Feature *)&g_example);
280        SAMGR_GetInstance()->RegisterFeatureApi(EXAMPLE_SERVICE, EXAMPLE_FEATURE, GET_IUNKNOWN(g_example));
281    }
282    ```
283
284-   定义功能的初始化入口:
285
286    ```
287    SYSEX_FEATURE_INIT(Init);
288
289    ```
290
291
292## 开发进程内对外接口<a name="section1685211117463"></a>
293
294-   定义IUnknown接口:
295
296    ```
297    typedef struct DemoApi {
298        INHERIT_IUNKNOWN;
299        BOOL (*AsyncCall)(IUnknown *iUnknown, const char *buff);
300        BOOL (*AsyncTimeCall)(IUnknown *iUnknown);
301        BOOL (*SyncCall)(IUnknown *iUnknown, struct Payload *payload);
302        BOOL (*AsyncCallBack)(IUnknown *iUnknown, const char *buff, Handler handler);
303    } DemoApi;
304    ```
305
306-   定义IUnknown的引用对象:
307
308    ```
309    typedef struct DemoRefApi {
310        INHERIT_IUNKNOWNENTRY(DemoApi);
311    } DemoRefApi;
312    ```
313
314-   初始化接口对象:
315
316    ```
317    static DemoRefApi api = {
318        DEFAULT_IUNKNOWN_ENTRY_BEGIN,
319            .AsyncCall = AsyncCall,
320            .AsyncTimeCall = AsyncTimeCall,
321            .SyncCall = SyncCall,
322            .AsyncCallBack = AsyncCallBack,
323        DEFAULT_IUNKNOWN_ENTRY_END,
324    };
325    ```
326
327-   注册服务接口:
328
329    ```
330    SAMGR_GetInstance()->RegisterFeatureApi(EXAMPLE_SERVICE, EXAMPLE_FEATURE, GET_IUNKNOWN(api));
331
332    ```
333
334
335## 调用进程内服务<a name="section3690162916462"></a>
336
337-   获取服务的对外接口:
338
339    ```
340    DemoApi *demoApi = NULL;
341    IUnknown *iUnknown = SAMGR_GetInstance()->GetFeatureApi(EXAMPLE_SERVICE, EXAMPLE_FEATURE);
342    if (iUnknown == NULL) {
343        return NULL;
344    }
345    int result = iUnknown->QueryInterface(iUnknown, DEFAULT_VERSION, (void **)&demoApi);
346    if (result != 0 || demoApi == NULL) {
347        return NULL;
348    }
349    ```
350
351-   接口调用:
352
353    ```
354    if (demoApi->AsyncCallBack == NULL) {
355        return NULL;
356    }
357    demoApi->AsyncCallBack((IUnknown *)demoApi, "I wanna async call callback good result!", AsyncHandler);
358    ```
359
360-   释放接口:
361
362    ```
363    int32 ref = demoApi->Release((IUnknown *)demoApi);
364
365    ```
366
367
368## 开发跨进程间对外接口<a name="section9220246194615"></a>
369
370-   继承IServerProxy替代继承IUnknown:INHERIT\_SERVER\_IPROXY
371
372    ```
373    typedef struct DemoFeatureApi {
374        INHERIT_SERVER_IPROXY;
375        BOOL (*AsyncCall)(IUnknown *iUnknown, const char *buff);
376        BOOL (*AsyncTimeCall)(IUnknown *iUnknown);
377        BOOL (*SyncCall)(IUnknown *iUnknown, struct Payload *payload);
378        BOOL (*AsyncCallBack)(IUnknown *iUnknown, const char *buff, IOwner notify, INotifyFunc handler);
379    } DemoFeatureApi;
380    ```
381
382-   初始化IServerProxy对象:
383
384    ```
385    static DemoFeature g_example = {
386        SERVER_IPROXY_IMPL_BEGIN,
387        .Invoke = Invoke,
388        .AsyncCall = AsyncCall,
389        .AsyncTimeCall = AsyncTimeCall,
390        .SyncCall = SyncCall,
391        .AsyncCallBack = AsyncCallBack,
392        IPROXY_END,
393    };
394    ```
395
396-   实现Invoke函数来处理Ipc消息:
397
398    ```
399    static int32 Invoke(IServerProxy *iProxy, int funcId, void *origin, IpcIo *req, IpcIo *reply)
400    {
401        DemoFeatureApi *api = (DemoFeatureApi *)iProxy;
402        BOOL ret;
403        size_t len = 0;
404        switch (funcId) {
405            case ID_ASYNCALL:
406                ret = api->AsyncCall((IUnknown *)iProxy, (char *)IpcIoPopString(req, &len));
407                IpcIoPushBool(reply, ret);
408                break;
409            case ID_ASYNTIMECALL:
410                ret = api->AsyncTimeCall((IUnknown *)iProxy);
411                IpcIoPushBool(reply, ret);
412                break;
413            case ID_SYNCCALL: {
414                struct Payload payload;
415                payload.id = IpcIoPopInt32(req);
416                payload.value = IpcIoPopInt32(req);
417                payload.name = (char *)IpcIoPopString(req, &len);
418                ret = api->SyncCall((IUnknown *)iProxy, &payload);
419                IpcIoPushString(reply, ret ? "TRUE" : "FALSE");
420            }
421                break;
422            case ID_ASYNCCALLBACK: { // convert to sync proxy
423                IpcIoPushString(reply, "Yes, you did!");
424                IpcIoPushBool(reply, TRUE);
425            }
426                break;
427            default:
428                IpcIoPushBool(reply, FALSE);
429                break;
430        }
431        return EC_SUCCESS;
432    }
433    ```
434
435-   注册接口:与进程内接口注册一致
436
437    ```
438    SAMGR_GetInstance()->RegisterFeatureApi(EXAMPLE_SERVICE, EXAMPLE_FEATURE, GET_IUNKNOWN(g_example));
439
440    ```
441
442
443## 调用跨进程间服务<a name="section114372711475"></a>
444
445-   获取跨进程服务的对外接口:
446
447    ```
448    IClientProxy *demoApi = NULL;
449    IUnknown *iUnknown = SAMGR_GetInstance()->GetFeatureApi(EXAMPLE_SERVICE, EXAMPLE_FEATURE);
450    if (iUnknown == NULL) {
451        return NULL;
452    }
453    int result = iUnknown->QueryInterface(iUnknown, CLIENT_PROXY_VER, (void **)&demoApi);
454    if (result != 0 || demoApi == NULL) {
455        return NULL;
456    }
457    ```
458
459-   调用Ipc消息接口:
460
461    ```
462    IpcIo request;char data[250];
463    IpcIoInit(&request, data, sizeof(data), 0);
464    demoApi->Invoke(demoApi, 0, &request, NULL, NULL);
465    ```
466
467-   释放接口:
468
469    ```
470    int32 ref = demoApi->Release((IUnknown *)demoApi);
471
472    ```
473
474
475## 开发跨进程间服务调用客户端代理<a name="section09341923114710"></a>
476
477-   定义IPC接口客户端代理:
478
479    ```
480    typedef struct DemoClientProxy {
481        INHERIT_CLIENT_IPROXY;
482        BOOL (*AsyncCall)(IUnknown *iUnknown, const char *buff);
483        BOOL (*AsyncTimeCall)(IUnknown *iUnknown);
484        BOOL (*SyncCall)(IUnknown *iUnknown, struct Payload *payload);
485        BOOL (*AsyncCallBack)(IUnknown *iUnknown, const char *buff, IOwner notify, INotifyFunc handler);
486    } DemoClientProxy;
487    typedef struct DemoClientEntry {
488        INHERIT_IUNKNOWNENTRY(DemoClientProxy);
489    } DemoClientEntry;
490    ```
491
492-   实现客户端代理封装Ipc消息接口:
493
494    ```
495    static BOOL AsyncCall(IUnknown *iUnknown, const char *buff)
496    {
497        DemoClientProxy *proxy = (DemoClientProxy *)iUnknown;
498        IpcIo request;
499        char data[MAX_DATA_LEN];
500        IpcIoInit(&request, data, MAX_DATA_LEN, 0);
501        IpcIoPushString(&request, buff);
502        int ret = proxy->Invoke((IClientProxy *)proxy, ID_ASYNCALL, &request, NULL, NULL);
503        return ret == EC_SUCCESS;
504    }
505
506    static BOOL AsyncTimeCall(IUnknown *iUnknown)
507    {
508        DemoClientProxy *proxy = (DemoClientProxy *)iUnknown;
509        IpcIo request;
510        char data[MAX_DATA_LEN];
511        IpcIoInit(&request, data, MAX_DATA_LEN, 0);
512        int ret = proxy->Invoke((IClientProxy *)proxy, ID_ASYNTIMECALL, &request, NULL, NULL);
513        return ret == EC_SUCCESS;
514    }
515
516    static int Callback(IOwner owner, int code, IpcIo *reply)
517    {
518        size_t len = 0;
519        return strcpy_s(owner, MAX_DATA_LEN, (char *)IpcIoPopString(reply, &len));
520    }
521
522    static BOOL SyncCall(IUnknown *iUnknown, struct Payload *payload)
523    {
524        DemoClientProxy *proxy = (DemoClientProxy *)iUnknown;
525        IpcIo request;
526        char data[MAX_DATA_LEN];
527        IpcIoInit(&request, data, MAX_DATA_LEN, 0);
528        IpcIoPushInt32(&request, payload->id);
529        IpcIoPushInt32(&request, payload->value);
530        IpcIoPushString(&request, payload->name);
531        int ret = proxy->Invoke((IClientProxy *)proxy, ID_SYNCCALL, &request, data, Callback);
532        data[MAX_DATA_LEN - 1] = 0;
533        HILOG_INFO(HILOG_MODULE_APP, "[TID:0x%lx]Remote response is %s!", pthread_self(), data);
534        return ret == EC_SUCCESS;
535    }
536
537    struct CurrentNotify {
538        IOwner notify;
539        INotifyFunc handler;
540    };
541
542    static int CurrentCallback(IOwner owner, int code, IpcIo *reply)
543    {
544        struct CurrentNotify *notify = (struct CurrentNotify *)owner;
545        size_t len = 0;
546        char *response = (char *)IpcIoPopString(reply, &len);
547        HILOG_INFO(HILOG_MODULE_APP, "[TID:0x%lx]Notify Remote response is %s!", pthread_self(), response);
548        notify->handler(notify->notify, response);
549        return EC_SUCCESS;
550    }
551
552    static BOOL AsyncCallBack(IUnknown *iUnknown, const char *buff, IOwner notify, INotifyFunc handler)
553    {
554        struct CurrentNotify owner = {notify, handler};
555        DemoClientProxy *proxy = (DemoClientProxy *)iUnknown;
556        IpcIo request;
557        char data[MAX_DATA_LEN];
558        IpcIoInit(&request, data, MAX_DATA_LEN, 0);
559        IpcIoPushString(&request, buff);
560        int ret = proxy->Invoke((IClientProxy *)proxy, ID_ASYNCCALLBACK, &request, &owner, CurrentCallback);
561        return ret == EC_SUCCESS;
562    }
563    ```
564
565-   实现客户端代理的工厂方法:
566
567    ```
568    void *DEMO_CreatClient(const char *service, const char *feature, uint32 size)
569    {
570        (void)service;
571        (void)feature;
572        uint32 len = size + sizeof(DemoClientEntry);
573        uint8 *client = malloc(len);
574        (void)memset_s(client, len, 0, len);
575        DemoClientEntry *entry = (DemoClientEntry *)&client[size];
576        entry->ver = ((uint16)CLIENT_PROXY_VER | (uint16)DEFAULT_VERSION);
577        entry->ref = 1;
578        entry->iUnknown.QueryInterface = IUNKNOWN_QueryInterface;
579        entry->iUnknown.AddRef = IUNKNOWN_AddRef;
580        entry->iUnknown.Release = IUNKNOWN_Release;
581        entry->iUnknown.Invoke = NULL;
582        entry->iUnknown.AsyncCall = AsyncCall;
583        entry->iUnknown.AsyncTimeCall = AsyncTimeCall;
584        entry->iUnknown.SyncCall = SyncCall;
585        entry->iUnknown.AsyncCallBack = AsyncCallBack;
586        return client;
587    }
588    void DEMO_DestroyClient(const char *service, const char *feature, void *iproxy)
589    {
590        free(iproxy);
591    }
592    ```
593
594-   将客户端代理的工厂方法注册到SAMGR:
595
596    ```
597    SAMGR_RegisterFactory(EXAMPLE_SERVICE, EXAMPLE_FEATURE, DEMO_CreatClient, DEMO_DestroyClient);
598    ```
599
600-   获取跨进程服务的对外接口:
601
602    ```
603    DemoClientProxy *demoApi = NULL;
604    IUnknown *iUnknown = SAMGR_GetInstance()->GetFeatureApi(EXAMPLE_SERVICE, EXAMPLE_FEATURE);
605    if (iUnknown == NULL) {
606        return NULL;
607    }
608    int result = iUnknown->QueryInterface(iUnknown, DEFAULT_VERSION, (void **)&demoApi);
609    if (result != 0 || demoApi == NULL) {
610        return NULL;
611    }
612    ```
613
614-   调用跨进程服务的客户端代理接口:
615
616    ```
617    if (demoApi->AsyncCallBack == NULL) {
618        return NULL;
619    }
620    demoApi->AsyncCallBack((IUnknown *)demoApi,
621                           "I wanna async call callback good result!", NULL, AsyncHandler);
622    ```
623
624-   释放接口:
625
626    ```
627    int32 ref = demoApi->Release((IUnknown *)demoApi);
628    ```
629
630
631## 相关仓<a name="section10365113863719"></a>
632
633系统服务管理子系统
634
635[**systemabilitymgr\_samgr\_lite**](https://gitee.com/openharmony/systemabilitymgr_samgr_lite)
636
637[systemabilitymgr\_samgr](https://gitee.com/openharmony/systemabilitymgr_samgr)
638
639[systemabilitymgr\_safwk](https://gitee.com/openharmony/systemabilitymgr_safwk)
640
641[systemabilitymgr\_safwk\_lite](https://gitee.com/openharmony/systemabilitymgr_safwk_lite)
642
643