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 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 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