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