# IPC & RPC Development Guidelines ## When to Use IPC/RPC enables a proxy and a stub that run on different processes to communicate with each other, regardless of whether they run on the same or different devices. ## Available APIs **Table 1** Native IPC APIs

Class/Interface

Function

Description

IRemoteBroker

sptr<IRemoteObject> AsObject()

Obtains the holder of a remote proxy object. This method must be implemented by the derived classes of IRemoteBroker. If you call this method on the stub, the RemoteObject is returned; if you call this method on the proxy, the proxy object is returned.

IRemoteStub

virtual int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)

Called to process a request from the proxy and return the result. Derived classes need to override this method.

IRemoteProxy

  

Service proxy classes are derived from the IRemoteProxy class.

## How to Develop **Using Native APIs** 1. Define the IPC interface **ITestAbility**. **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. ``` class ITestAbility : public IRemoteBroker { public: // DECLARE_INTERFACE_DESCRIPTOR is mandatory, and the input parameter is std::u16string. DECLARE_INTERFACE_DESCRIPTOR(u"test.ITestAbility"); int TRANS_ID_PING_ABILITY = 1; // Define the message code. virtual int TestPingAbility(const std::u16string &dummy) = 0; // Define functions. }; ``` 2. Define and implement service provider **TestAbilityStub**. This class is related to the IPC framework and needs to inherit **IRemoteStub**. You need to override **OnRemoteRequest** on the stub to receive requests from the proxy. ``` class TestAbilityStub : public IRemoteStub { public: virtual int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; int TestPingAbility(const std::u16string &dummy) override; }; int TestServiceStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) { switch (code) { case TRANS_ID_PING_ABILITY: { std::u16string dummy = data.ReadString16(); int result = TestPingAbility(dummy); reply.WriteInt32(result); return 0; } default: return IPCObjectStub::OnRemoteRequest(code, data, reply, option); } } ``` 3. Define the **TestAbility** class that implements functions for the stub. ``` class TestAbility : public TestAbilityStub { public: int TestPingAbility(const std::u16string &dummy); } int TestAbility::TestPingAbility(const std::u16string &dummy) { return 0; } ``` 4. Define and implement **TestAbilityProxy**. This class is implemented on the proxy and inherits **IRemoteProxy**. You can call **SendRequest** to send a request to the stub and expose the capabilities provided by the stub. ``` class TestAbilityProxy : public IRemoteProxy { public: explicit TestAbilityProxy(const sptr &impl); int TestPingService(const std::u16string &dummy) override; private: static inline BrokerDelegator delegator_; // Use the iface_cast macro. } TestAbilityProxy::TestAbilityProxy(const sptr &impl) : IRemoteProxy(impl) { } int TestAbilityProxy::TestPingService(const std::u16string &dummy) { MessageOption option; MessageParcel dataParcel, replyParcel; dataParcel.WriteString16(dummy); int error = Remote()->SendRequest(TRANS_ID_PING_ABILITY, dataParcel, replyParcel, option); int result = (error == ERR_NONE) ? replyParcel.ReadInt32() : -1; return result; } ``` 5. Register and start an SA. Call **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. ``` // Register the TestAbilityStub instance with the SystemAbilityManager on the same device as the SA. auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); samgr->AddSystemAbility(said, new TestAbility()); // Register the TestAbilityStub instance with the SystemAbilityManager on a different device. auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); ISystemAbilityManager::SAExtraProp saExtra; saExtra.isDistributed = true; // Set a distributed SA. int result = samgr->AddSystemAbility(said, new TestAbility(), saExtra); ``` 6. Obtain the SA. Call the **GetSystemAbility** function of the **SystemAbilityManager** class to obtain the **IRemoteObject** for the SA, and create a **TestAbilityProxy** instance. ``` // Obtain the proxy of the SA registered on the local device. sptr samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); sptr remoteObject = samgr->GetSystemAbility(said); sptr testAbility = iface_cast(remoteObject); // Use the iface_cast macro to convert the proxy to a specific type. // Obtain the proxies of the SAs registered with other devices. sptr samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); sptr remoteObject = samgr->GetSystemAbility(sdid, deviceId); // deviceId identifies a device. sptr proxy(new TestAbilityProxy(remoteObject)); // Construct a proxy. ```