Name |
Date |
Size |
#Lines |
LOC |
||
---|---|---|---|---|---|---|
.. | - | - | ||||
figures/ | 12-May-2024 | - | ||||
interfaces/ | 12-May-2024 | - | 2,109 | 1,556 | ||
ipc/ | 12-May-2024 | - | 35,275 | 27,413 | ||
services/dbinder/ | 12-May-2024 | - | 6,610 | 4,786 | ||
test/resource/ | 12-May-2024 | - | 62 | 34 | ||
utils/ | 12-May-2024 | - | 231 | 151 | ||
.gitattributes | D | 12-May-2024 | 631 | 16 | 15 | |
BUILD.gn | D | 12-May-2024 | 1.2 KiB | 41 | 35 | |
LICENSE | D | 12-May-2024 | 9.9 KiB | 179 | 150 | |
README.md | D | 12-May-2024 | 12.1 KiB | 263 | 197 | |
README_zh.md | D | 12-May-2024 | 18.1 KiB | 446 | 332 | |
bundle.json | D | 12-May-2024 | 3.4 KiB | 98 | 98 |
README.md
1# communication\_ipc<a name="EN-US_TOPIC_0000001103602398"></a> 2 3- [Introduction](#section11660541593) 4- [Architecture](#section1950291414611) 5- [Directory Structure](#section161941989596) 6- [Constraints](#section119744591305) 7- [Compilation and Building](#section137768191623) 8- [Usage](#section1312121216216) 9 - [Available APIs](#section1551164914237) 10 - [Usage Guidelines](#section129654513264) 11 12- [Repositories Involved](#section1371113476307) 13 14## Introduction<a name="section11660541593"></a> 15 16The inter-process communication \(IPC\) and remote procedure call \(RPC\) mechanisms are used to implement cross-process communication. The difference between them lies in that IPC uses the Binder driver to implement cross-process communication within a device, whereas RPC uses the DSoftBus driver to implement cross-process communication across devices. IPC and RPC generally use a client-server model. The service requester \(client\) can obtain the proxy of the service provider \(server\) and use the proxy to read and write data, thus implementing data communication between processes. Generally, the server registers system abilities \(SAs\) with the system ability manager \(SAMgr\), which manages the SAs and provides APIs for the client. To communicate with a specific SA, the client must obtain the proxy of the SA from SAMgr. In this document, Proxy represents the service requester, and Stub represents the service provider. 17 18## Architecture<a name="section1950291414611"></a> 19 20**Figure 1** IPC architecture<a name="fig312319321710"></a> 21 22 23## Directory Structure<a name="section161941989596"></a> 24 25``` 26/foundation/communication/ipc 27├── interfaces # APIs exposed externally 28│ └── innerkits # Header files for internal subsystems 29│ ├── ipc_core # IPC APIs 30│ └── libdbinder # dbinder APIs 31├── ipc # IPC framework 32│ ├── native # IPC native implementation 33│ ├── src # IPC native source code 34│ └── test # IPC native unit test cases 35│ └── test # IPC native module test cases 36├── service # dbinder implementation 37│ └── dbinder # dbinder source code 38``` 39 40## Constraints<a name="section119744591305"></a> 41 42Currently, cross-device RPC communication is not supported. 43 44## Compilation and Building<a name="section137768191623"></a> 45 46**Native Dependency** 47 48SDK dependency: 49 50``` 51external_deps = [ 52 "ipc:ipc_core", 53] 54``` 55 56In addition, the refbase implementation on which IPC/RPC depends is stored in **//utils**. Add the dependency on the Utils source code. 57 58``` 59deps = [ 60 "//utils/native/base:utils", 61] 62``` 63 64## Usage<a name="section1312121216216"></a> 65 66The procedure for implementing cross-process communication using native APIs is similar to that using Java APIs. 67 681. Define an interface. 69 70 The interface inherits **IRemoteBroker** and defines descriptors, functions, and message code. 71 722. Implement the server provider \(stub\). 73 74 The stub inherits **IRemoteStub\(Native\)** or **RemoteObject\(Java\)** as well as **AsObject** and **OnRemoteRequest**. 75 763. Implement the service requester \(proxy\). 77 78 The proxy inherits **IRemoteProxy\(Native\)** or **RemoteProxy\(Java\)**, encapsulates functions, and calls **SendRequest** to send requests to the stub. 79 804. Register an SA. 81 82 After the process where the service provider resides starts, apply for the unique SA ID and register the stub with SAMgr. 83 845. Obtain the SA. 856. Obtain the proxy from the SAMgr based on the SA ID and device ID, and implement cross-process communication with the stub through the proxy. 86 87### Available APIs<a name="section1551164914237"></a> 88 89**Table 1** Native IPC APIs 90 91<a name="table178849240013"></a> 92<table><thead align="left"><tr id="row6884924608"><th class="cellrowborder" valign="top" width="14.12141214121412%" id="mcps1.2.4.1.1"><p id="p98846241706"><a name="p98846241706"></a><a name="p98846241706"></a>Class/Interface</p> 93</th> 94<th class="cellrowborder" valign="top" width="52.54525452545254%" id="mcps1.2.4.1.2"><p id="p1488482414020"><a name="p1488482414020"></a><a name="p1488482414020"></a>Method</p> 95</th> 96<th class="cellrowborder" valign="top" width="33.33333333333333%" id="mcps1.2.4.1.3"><p id="p388516244016"><a name="p388516244016"></a><a name="p388516244016"></a>Description</p> 97</th> 98</tr> 99</thead> 100<tbody><tr id="row15885824402"><td class="cellrowborder" valign="top" width="14.12141214121412%" headers="mcps1.2.4.1.1 "><p id="p08859241008"><a name="p08859241008"></a><a name="p08859241008"></a>IRemoteBroker</p> 101</td> 102<td class="cellrowborder" valign="top" width="52.54525452545254%" headers="mcps1.2.4.1.2 "><p id="p388572412010"><a name="p388572412010"></a><a name="p388572412010"></a>sptr<IRemoteObject> AsObject()</p> 103</td> 104<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.3 "><p id="p13885724405"><a name="p13885724405"></a><a name="p13885724405"></a>Obtains the holder of a remote proxy object. This method must be implemented by the derived classes of <strong id="b9012379013"><a name="b9012379013"></a><a name="b9012379013"></a>IRemoteBroker</strong>. If you call this method on the stub, the <strong id="b11613719015"><a name="b11613719015"></a><a name="b11613719015"></a>RemoteObject</strong> is returned; if you call this method on the proxy, the proxy object is returned.</p> 105</td> 106</tr> 107<tr id="row138859241808"><td class="cellrowborder" valign="top" width="14.12141214121412%" headers="mcps1.2.4.1.1 "><p id="p1888515245012"><a name="p1888515245012"></a><a name="p1888515245012"></a>IRemoteStub</p> 108</td> 109<td class="cellrowborder" valign="top" width="52.54525452545254%" headers="mcps1.2.4.1.2 "><p id="p1388516240011"><a name="p1388516240011"></a><a name="p1388516240011"></a>virtual int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)</p> 110</td> 111<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.3 "><p id="p1188582414016"><a name="p1188582414016"></a><a name="p1188582414016"></a>Called to process a request from the proxy and return the result. Derived classes need to override this method.</p> 112</td> 113</tr> 114<tr id="row108856241904"><td class="cellrowborder" valign="top" width="14.12141214121412%" headers="mcps1.2.4.1.1 "><p id="p6885924609"><a name="p6885924609"></a><a name="p6885924609"></a>IRemoteProxy</p> 115</td> 116<td class="cellrowborder" valign="top" width="52.54525452545254%" headers="mcps1.2.4.1.2 "> </td> 117<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.3 "><p id="p688592413018"><a name="p688592413018"></a><a name="p688592413018"></a>Service proxy classes are derived from the <strong id="b8934204311212"><a name="b8934204311212"></a><a name="b8934204311212"></a>IRemoteProxy</strong> class.</p> 118</td> 119</tr> 120</tbody> 121</table> 122 123### Usage Guidelines<a name="section129654513264"></a> 124 125**Native** 126 127Define the IPC interface **ITestAbility**. 128 129**ITestAbility** inherits the IPC base class **IRemoteBroker** and defines descriptors, functions, and message code. The functions need to be implemented on both the proxy and stub. 130 131``` 132class ITestAbility : public IRemoteBroker { 133public: 134// DECLARE_INTERFACE_DESCRIPTOR is mandatory, and the input parameter is std::u16string. 135DECLARE_INTERFACE_DESCRIPTOR(u"test.ITestAbility"); 136int TRANS_ID_PING_ABILITY = 1; // Define the message code. 137virtual int TestPingAbility(const std::u16string &dummy) = 0; // Define functions. 138}; 139``` 140 141Define and implement service provider **TestAbilityStub**. 142 143This class is related to the IPC framework and needs to inherit **IRemoteStub<ITestAbility\>**. You need to override **OnRemoteRequest** on the stub to receive requests from the proxy. 144 145``` 146class TestAbilityStub : public IRemoteStub<ITestAbility> { 147public: 148 virtual int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; 149 int TestPingAbility(const std::u16string &dummy) override; 150}; 151 152int TestServiceStub::OnRemoteRequest(uint32_t code, 153 MessageParcel &data, MessageParcel &reply, MessageOption &option) 154{ 155 switch (code) { 156 case TRANS_ID_PING_ABILITY: { 157 std::u16string dummy = data.ReadString16(); 158 int result = TestPingAbility(dummy); 159 reply.WriteInt32(result); 160 return 0; 161 } 162 default: 163 return IPCObjectStub::OnRemoteRequest(code, data, reply, option); 164 } 165} 166``` 167 168Define the **TestAbility** class that implements functions for the stub. 169 170``` 171class TestAbility : public TestAbilityStub { 172public: 173 int TestPingAbility(const std::u16string &dummy); 174} 175 176int TestAbility::TestPingAbility(const std::u16string &dummy) { 177 return 0; 178} 179``` 180 181Define and implement **TestAbilityProxy**. 182 183This class is implemented on the proxy and inherits **IRemoteProxy<ITestAbility\>**. You can call **SendRequest** to send a request to the stub and expose the capabilities provided by the stub. 184 185``` 186class TestAbilityProxy : public IRemoteProxy<ITestAbility> { 187public: 188 explicit TestAbilityProxy(const sptr<IRemoteObject> &impl); 189 int TestPingService(const std::u16string &dummy) override; 190private: 191 static inline BrokerDelegator<TestAbilityProxy> delegator_; // Use the iface_cast macro. 192} 193 194TestAbilityProxy::TestAbilityProxy(const sptr<IRemoteObject> &impl) 195 : IRemoteProxy<ITestAbility>(impl) 196{ 197} 198 199int TestAbilityProxy::TestPingService(const std::u16string &dummy) { 200 MessageOption option; 201 MessageParcel dataParcel, replyParcel; 202 dataParcel.WriteString16(dummy); 203 int error = Remote()->SendRequest(TRANS_ID_PING_ABILITY, dataParcel, replyParcel, option); 204 int result = (error == ERR_NONE) ? replyParcel.ReadInt32() : -1; 205 return result; 206} 207``` 208 209Send a request synchronously or asynchronously. 210 211The **MessageOption** parameter for the **sendRequest\(\)** method can be set to **TF\_SYNC**, **TF\_ASYNC**, or **TF\_ACCEPT\_FDS** using the **MessageOption** constructor or **void SetFlags\(int flags\)**. The default value is **TF\_SYNC**. 212 213``` 214int SendRequest(uint32_t code, MessageParcel &data, 215 MessageParcel &reply, MessageOption &option) override; 216MessageOption option = { MessageOption::TF_ASYNC }; 217``` 218 219Register and start an SA. 220 221Call **AddSystemAbility** to register the **TestAbilityStub** instance of the SA with **SystemAbilityManager**. The registration parameters vary depending on whether the **SystemAbilityManager** resides on the same device as the SA. 222 223``` 224// Register the TestAbilityStub instance with the SystemAbilityManager on the same device as the SA. 225auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); 226samgr->AddSystemAbility(said, new TestAbility()); 227 228// Register the TestAbilityStub instance with the SystemAbilityManager on a different device. 229auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); 230ISystemAbilityManager::SAExtraProp saExtra; 231saExtra.isDistributed = true; // Set a distributed SA. 232int result = samgr->AddSystemAbility(said, new TestAbility(), saExtra); 233``` 234 235Obtain the SA. 236 237Call the **GetSystemAbility** function of the **SystemAbilityManager** class to obtain the **IRemoteObject** for the SA, and create a **TestAbilityProxy** instance. 238 239``` 240// Obtain the proxy of the SA registered on the local device. 241sptr<ISystemAbilityManager> samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); 242sptr<IRemoteObject> remoteObject = samgr->GetSystemAbility(said); 243sptr<ITestAbility> testAbility = iface_cast<ITestAbility>(remoteObject); // Use the iface_cast macro to convert the proxy to a specific type. 244 245// Obtain the proxies of the SAs registered with other devices. 246sptr<ISystemAbilityManager> samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); 247sptr<IRemoteObject> remoteObject = samgr->GetSystemAbility(sdid, deviceId); // deviceId identifies a device. 248sptr<TestAbilityProxy> proxy(new TestAbilityProxy(remoteObject)); // Construct a proxy. 249``` 250 251## Repositories Involved<a name="section1371113476307"></a> 252 253DSoftBus subsystem 254 255**communication\_ipc** 256 257utils 258 259utils\_native 260 261distributedschedule\_samgr 262 263
README_zh.md
1# IPC/RPC组件<a name="ZH-CN_TOPIC_0000001103602398"></a> 2 3- [简介](#section11660541593) 4- [系统架构](#section1950291414611) 5- [目录](#section161941989596) 6- [约束](#section119744591305) 7- [编译构建](#section137768191623) 8- [说明](#section1312121216216) 9 - [接口说明](#section1551164914237) 10 - [使用说明](#section129654513264) 11 12- [相关仓](#section1371113476307) 13 14## 简介<a name="section11660541593"></a> 15 16IPC(Inter-Process Communication)与RPC(Remote Procedure Call)机制用于实现跨进程通信,不同的是前者使用Binder驱动,用于设备内的跨进程通信,而后者使用软总线驱动,用于跨设备跨进程通信。IPC和RPC通常采用客户端-服务器(Client-Server)模型,服务请求方(Client)可获取提供服务提供方(Server)的代理 (Proxy),并通过此代理读写数据来实现进程间的数据通信。通常,系统能力(System Ability)Server侧会先注册到系统能力管理者(System Ability Manager,缩写SAMgr)中,SAMgr负责管理这些SA并向Client提供相关的接口。Client要和某个具体的SA通信,必须先从SAMgr中获取该SA的代理,然后使用代理和SA通信。三方应用可以使用FA提供的接口绑定服务提供方的Ability,获取代理,进行通信。下文使用Proxy表示服务请求方,Stub表示服务提供方。 17 18## 系统架构<a name="section1950291414611"></a> 19 20**图 1** IPC通信机制架构图<a name="fig312319321710"></a> 21 22 23## 目录<a name="section161941989596"></a> 24 25``` 26/foundation/communication/ipc 27├── interfaces # 对外接口存放目录 28│ └── innerkits # 对内部子系统暴露的头文件存放目录 29│ ├── ipc_core # ipc 接口存放目录 30│ └── libdbinder # dbinder 接口存放目录 31├── ipc # ipc 框架代码 32│ ├── native # ipc native 实现存放目录 33│ ├── src # ipc native 源代码存放目录 34│ └── test # ipc native 单元测试用例存放目录 35│ └── test # ipc native 模块测试用例存放目录 36├── service # dbinder 实现存放目录 37│ └── dbinder # dbinder 源代码存放目录 38``` 39 40## 约束<a name="section119744591305"></a> 41 421. 单个设备上跨进程通信时,传输的数据量最大约为1MB,过大的数据量请使用匿名共享内存。 432. 不支持把跨设备的Proxy对象传递回该Proxy对象所指向的Stub对象所在的设备。 44 45## 编译构建<a name="section137768191623"></a> 46 47**JS侧依赖** 48 49``` 50import rpc from "@ohos.rpc" 51import featureAbility from "@ohos.ability.featureAbility" 52``` 53 54**Native侧编译依赖** 55 56sdk依赖: 57 58``` 59external_deps = [ 60 "ipc:ipc_core", 61] 62``` 63 64此外, IPC/RPC依赖的refbase实现在公共基础库实现//utils下,请增加对utils的源码依赖: 65 66``` 67deps = [ 68 "//utils/native/base:utils", 69] 70``` 71 72## 说明<a name="section1312121216216"></a> 73 74**JS侧实现跨进程通信基本步骤:** 75 761. 获取代理 77 78 使用ohos.ability.featureAbility提供的connectAbility方法绑定Ability,在参数里指定要绑定的Ability所在应用的包名、组件名,如果是跨设备的情况,还需要指定所在设备的ID。用户需要在服务端的onConnect方法里返回一个继承自ohos.rpc.RemoteObject的对象,此对象会在onRemoteRequest方法里接收到请求。 79 802. 发送请求 81 82 客户端在connectAbility参数指定的回调函数接收到代理对象后,使用ohos.rpc模块提供的方法完成RPC通信,其中MessageParcel提供了读写各种类型数据的方法,IRemoteObject提供了发送请求的方法,RemoteObject提供了处理请求的方法onRemoteRequest,用户需要重写。 83 84**Native侧实现跨进程通信的基本步骤:** 85 861. 定义接口类 87 88 接口类继承IRemoteBroker,定义描述符、业务函数和消息码。 89 902. 实现服务提供端\(Stub\) 91 92 Stub继承IRemoteStub\(Native\),除了接口类中未实现方法外,还需要实现AsObject方法及OnRemoteRequest方法。 93 943. 实现服务请求端\(Proxy\) 95 96 Proxy继承IRemoteProxy\(Native\),封装业务函数,调用SendRequest将请求发送到Stub。 97 984. 注册SA 99 100 服务提供方所在进程启动后,申请SA的唯一标识,将Stub注册到SAMgr。 101 1025. 获取SA 103 1046. 通过SA的标识和设备标识,从SAMgr获取Proxy,通过Proxy实现与Stub的跨进程通信。 105 106### 接口说明<a name="section1551164914237"></a> 107 108**表 1** JS侧IPC关键API 109 110| 模块 | 方法 | 功能说明 | 111| --------------------------- | ------------------------------------------------------------ | ------------------------------------------- | 112| ohos.ability.featureAbility | connectAbility(request: Want, options:ConnectOptions ): number | 绑定指定的Ability,在回调函数里接收代理对象 | 113| ohos.rpc.RemoteObject | onRemoteRequest(code: number, data: MessageParcel, reply: MessageParcel, options: MessageOption): boolean | 服务端处理请求,返回结果 | 114| ohos.rpc.IRemoteObject | sendRequest(code: number, data: MessageParcel, reply: MessageParcel, options: MessageOption): Promise<SendRequestResult> | 发送请求,在期约里接收结果 | 115| ohos.rpc.IRemoteObject | sendRequest(code: number, data: MessageParcel, reply: MessageParcel, options: MessageOption, callback: AsyncCallback<SendRequestResult>): void | 发送请求,在回调函数里接收结果 | 116| ohos.rpc.MessageParcel | writeRemoteObject(object: IRemoteObject): boolean | 序列化IRemoteObject对象 | 117| ohos.rpc.MessageParcel | readRemoteObject(): IRemoteObject | 反序列化IRemoteObject对象 | 118 119 120 121**表 2** Native侧IPC接口 122 123<a name="table178849240013"></a> 124 125<table><thead align="left"><tr id="row6884924608"><th class="cellrowborder" valign="top" width="14.12141214121412%" id="mcps1.2.4.1.1"><p id="p98846241706"><a name="p98846241706"></a><a name="p98846241706"></a>类/接口</p> 126</th> 127<th class="cellrowborder" valign="top" width="52.54525452545254%" id="mcps1.2.4.1.2"><p id="p1488482414020"><a name="p1488482414020"></a><a name="p1488482414020"></a>方法</p> 128</th> 129<th class="cellrowborder" valign="top" width="33.33333333333333%" id="mcps1.2.4.1.3"><p id="p388516244016"><a name="p388516244016"></a><a name="p388516244016"></a>功能说明</p> 130</th> 131</tr> 132</thead> 133<tbody><tr id="row15885824402"><td class="cellrowborder" valign="top" width="14.12141214121412%" headers="mcps1.2.4.1.1 "><p id="p08859241008"><a name="p08859241008"></a><a name="p08859241008"></a>IRemoteBroker</p> 134</td> 135<td class="cellrowborder" valign="top" width="52.54525452545254%" headers="mcps1.2.4.1.2 "><p id="p388572412010"><a name="p388572412010"></a><a name="p388572412010"></a>sptr<IRemoteObject> AsObject()</p> 136</td> 137<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.3 "><p id="p13885724405"><a name="p13885724405"></a><a name="p13885724405"></a>返回通信对象。派生类需要实现,Stub端返回RemoteObject对象本身,Proxy端返回代理对象。</p> 138</td> 139</tr> 140<tr id="row138859241808"><td class="cellrowborder" valign="top" width="14.12141214121412%" headers="mcps1.2.4.1.1 "><p id="p1888515245012"><a name="p1888515245012"></a><a name="p1888515245012"></a>IRemoteStub</p> 141</td> 142<td class="cellrowborder" valign="top" width="52.54525452545254%" headers="mcps1.2.4.1.2 "><p id="p1388516240011"><a name="p1388516240011"></a><a name="p1388516240011"></a>virtual int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)</p> 143</td> 144<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.3 "><p id="p1188582414016"><a name="p1188582414016"></a><a name="p1188582414016"></a>请求处理方法,派生类需要重写,处理Proxy的请求并返回结果。</p> 145</td> 146</tr> 147<tr id="row108856241904"><td class="cellrowborder" valign="top" width="14.12141214121412%" headers="mcps1.2.4.1.1 "><p id="p6885924609"><a name="p6885924609"></a><a name="p6885924609"></a>IRemoteProxy</p> 148</td> 149<td class="cellrowborder" valign="top" width="52.54525452545254%" headers="mcps1.2.4.1.2 "> </td> 150<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.3 "><p id="p688592413018"><a name="p688592413018"></a><a name="p688592413018"></a>业务Proxy类派生自IRemoteProxy类。</p> 151</td> 152</tr> 153</tbody> 154</table> 155 156### 使用说明<a name="section129654513264"></a> 157 158**JS侧使用说明** 159 1601. 客户端构造变量want,指定要绑定的Ability所在应用的包名、组件名,如果是跨设备的场景,还需要目标设备ID。构造变量connect,指定绑定成功、绑定失败、断开连接时的回调函数。使用featureAbility提供的接口绑定Ability。 161 162 ``` 163 import rpc from "@ohos.rpc" 164 import featureAbility from "@ohos.ability.featureAbility" 165 166 let proxy = null 167 let connectId = null 168 169 // 单个设备 170 let want = { 171 // 包名和组件名写实际的值 172 "bundleName": "ohos.rpc.test.server", 173 "abilityName": "ohos.rpc.test.server.ServiceAbility", 174 } 175 let connect = { 176 onConnect:function(elementName, remote) { 177 proxy = remote 178 }, 179 onDisconnect:function(elementName) { 180 }, 181 onFailed:function() { 182 proxy = null 183 } 184 } 185 connectId = featureAbility.connectAbility(want, connect) 186 187 // 如果是跨设备绑定,可以使用deviceManager获取目标设备ID 188 import deviceManager from '@ohos.distributedHardware.deviceManager' 189 function deviceManagerCallback(deviceManager) { 190 let deviceList = deviceManager.getTrustedDeviceListSync() 191 let deviceId = deviceList[0].deviceId 192 let want = { 193 "bundleName": "ohos.rpc.test.server", 194 "abilityName": "ohos.rpc.test.service.ServiceAbility", 195 "deviceId": deviceId, 196 "flags": 256 197 } 198 connectId = featureAbility.connectAbility(want, connect) 199 } 200 // 第一个参数是本应用的包名,第二个参数是接收deviceManager的回调函数 201 deviceManager.createDeviceManager("ohos.rpc.test", deviceManagerCallback) 202 ``` 203 204 205 2062. 服务端被绑定的Ability在onConnect方法里返回继承自rpc.RemoteObject的对象,该对象需要实现onRemoteRequest方法,处理客户端的请求。 207 208 ``` 209 import rpc from "@ohos.rpc" 210 onConnect(want) { 211 return new Stub("rpcTestAbility") 212 } 213 class Stub extends rpc.RemoteObject { 214 constructor(descriptor) { 215 super(descriptor) 216 } 217 onRemoteRequest(code, data, reply, option) { 218 // 根据code处理客户端的请求 219 return true 220 } 221 } 222 ``` 223 224 225 2263. 客户端在onConnect回调里接收到代理对象,调用sendRequest方法发起请求,在期约或者回调函数里接收结果。 227 228 ``` 229 import rpc from "@ohos.rpc" 230 // 使用期约 231 let option = new rpc.MessageOption() 232 let data = rpc.MessageParcel.create() 233 let reply = rpc.MessageParcel.create() 234 // 往data里写入参数 235 proxy.sendRequest(1, data, reply, option) 236 .then(function(result) { 237 if (result.errCode != 0) { 238 console.error("send request failed, errCode: " + result.errCode) 239 return 240 } 241 // 从result.reply里读取结果 242 }) 243 .catch(function(e) { 244 console.error("send request got exception: " + e) 245 } 246 .finally(() => { 247 data.reclaim() 248 reply.reclaim() 249 }) 250 251 // 使用回调函数 252 function sendRequestCallback(result) { 253 try { 254 if (result.errCode != 0) { 255 console.error("send request failed, errCode: " + result.errCode) 256 return 257 } 258 // 从result.reply里读取结果 259 } finally { 260 result.data.reclaim() 261 result.reply.reclaim() 262 } 263 } 264 let option = new rpc.MessageOption() 265 let data = rpc.MessageParcel.create() 266 let reply = rpc.MessageParcel.create() 267 // 往data里写入参数 268 proxy.sendRequest(1, data, reply, option, sendRequestCallback) 269 ``` 270 271 272 2734. IPC通信结束后,使用featureAbility的接口断开连接。 274 275 ``` 276 import rpc from "@ohos.rpc" 277 import featureAbility from "@ohos.ability.featureAbility" 278 function disconnectCallback() { 279 console.info("disconnect ability done") 280 } 281 featureAbility.disconnectAbility(connectId, disconnectCallback) 282 ``` 283 284 285 286**Native侧使用说明** 287 2881. 定义IPC接口ITestAbility 289 290 IPC接口继承IPC基类接口IRemoteBroker,接口里定义描述符、业务函数和消息码,其中业务函数在Proxy端和Stub端都需要实现。 291 292 ``` 293 class ITestAbility : public IRemoteBroker { 294 public: 295 // DECLARE_INTERFACE_DESCRIPTOR是必须的, 入参需使用std::u16string; 296 DECLARE_INTERFACE_DESCRIPTOR(u"test.ITestAbility"); // DESCRIPTOR接口描述符建议使用"组件名.类名"的格式 297 int TRANS_ID_PING_ABILITY = 1; // 定义消息码 298 virtual int TestPingAbility(const std::u16string &dummy) = 0; // 定义业务函数 299 }; 300 ``` 301 302 303 3042. 定义和实现服务端TestAbilityStub 305 306 该类是和IPC框架相关的实现,需要继承 IRemoteStub<ITestAbility\>。Stub端作为接收请求的一端,需重写OnRemoteRequest方法用于接收客户端调用。 307 308 ``` 309 class TestAbilityStub : public IRemoteStub<ITestAbility> { 310 public: 311 virtual int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; 312 int TestPingAbility(const std::u16string &dummy) override; 313 }; 314 315 int TestServiceStub::OnRemoteRequest(uint32_t code, 316 MessageParcel &data, MessageParcel &reply, MessageOption &option) 317 { 318 if (data.ReadInterfaceToken() != GetDescriptor()) { //校验是否为本服务的接口描述符,避免中继攻击 319 return -1; 320 } 321 switch (code) { 322 case TRANS_ID_PING_ABILITY: { 323 std::u16string dummy = data.ReadString16(); 324 int result = TestPingAbility(dummy); 325 reply.WriteInt32(result); 326 return 0; 327 } 328 default: 329 return IPCObjectStub::OnRemoteRequest(code, data, reply, option); 330 } 331 } 332 ``` 333 334 335 3363. 定义服务端业务函数具体实现类TestAbility 337 338 ``` 339 class TestAbility : public TestAbilityStub { 340 public: 341 int TestPingAbility(const std::u16string &dummy); 342 } 343 344 int TestAbility::TestPingAbility(const std::u16string &dummy) { 345 return 0; 346 } 347 ``` 348 349 350 3514. 定义和实现客户端TestAbilityProxy 352 353 该类是Proxy端实现,继承IRemoteProxy<ITestAbility\>,调用SendRequest接口向Stub端发送请求,对外暴露服务端提供的能力。 354 355 ``` 356 class TestAbilityProxy : public IRemoteProxy<ITestAbility> { 357 public: 358 explicit TestAbilityProxy(const sptr<IRemoteObject> &impl); 359 int TestPingService(const std::u16string &dummy) override; 360 private: 361 static inline BrokerDelegator<TestAbilityProxy> delegator_; // 方便使用iface_cast宏 362 } 363 364 TestAbilityProxy::TestAbilityProxy(const sptr<IRemoteObject> &impl) 365 : IRemoteProxy<ITestAbility>(impl) 366 { 367 } 368 369 int TestAbilityProxy::TestPingService(const std::u16string &dummy) { 370 MessageOption option; 371 MessageParcel dataParcel, replyParcel; 372 if(!dataParcel.WriteInterfaceToken(GetDescriptor())) { //所有对外接口的proxy实现都要写入接口描述符,用于stub端检验 373 return -1; 374 } 375 if(!dataParcel.WriteString16(dummy)) { 376 return -1; 377 } 378 int error = Remote()->SendRequest(TRANS_ID_PING_ABILITY, dataParcel, replyParcel, option); 379 int result = (error == ERR_NONE) ? replyParcel.ReadInt32() : -1; 380 return result; 381 } 382 ``` 383 384 385 3865. 同步调用与异步调用 387 388 essageOption作为发送接口(原型如下)的入参,可设定同步(TF\_SYNC)、异步(TF\_ASYNC)、接收FD(TF\_ACCEPT\_FDS),默认情况下设定为同步,其余可通过MessageOption构造方法或void SetFlags\(int flags\)设定。 389 390 ``` 391 int SendRequest(uint32_t code, MessageParcel &data, 392 MessageParcel &reply, MessageOption &option) override; 393 MessageOption option = { MessageOption::TF_ASYNC }; 394 ``` 395 396 397 3986. SA注册与启动 399 400 SA需要将自己的TestAbilityStub实例通过AddSystemAbility接口注册到SystemAbilityManager,设备内与分布式的注册参数不同。 401 402 ``` 403 // 注册到本设备内 404 auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); 405 samgr->AddSystemAbility(said, new TestAbility()); 406 407 // 在组网场景下,会被同步到其他设备上 408 auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); 409 ISystemAbilityManager::SAExtraProp saExtra; 410 saExtra.isDistributed = true; // 设置为分布式SA 411 int result = samgr->AddSystemAbility(said, new TestAbility(), saExtra); 412 ``` 413 414 415 4167. SA获取与调用 417 418 通过SystemAbilityManager的GetSystemAbility方法可获取到对应SA的代理IRemoteObject,然后构造TestAbilityProxy即可。 419 420 ``` 421 // 获取本设备内注册的SA的proxy 422 sptr<ISystemAbilityManager> samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); 423 sptr<IRemoteObject> remoteObject = samgr->GetSystemAbility(said); 424 sptr<ITestAbility> testAbility = iface_cast<ITestAbility>(remoteObject); // 使用iface_cast宏转换成具体类型 425 426 // 获取其他设备注册的SA的Proxy 427 sptr<ISystemAbilityManager> samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); 428 sptr<IRemoteObject> remoteObject = samgr->GetSystemAbility(sdid, deviceId); // deviceId是指定设备的标识符 429 sptr<TestAbilityProxy> proxy(new TestAbilityProxy(remoteObject)); // 直接构造具体Proxy 430 ``` 431 432 433 434## 相关仓<a name="section1371113476307"></a> 435 436分布式软总线子系统 437 438**communication\_ipc** 439 440utils 441 442utils\_native 443 444distributedschedule\_samgr 445 446