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