未验证 提交 359faf01 编写于 作者: O openharmony_ci 提交者: Gitee

!13506 翻译已完成12868+12649

Merge pull request !13506 from shawn_he/12868-b
# IPC & RPC Development<a name="EN-US_TOPIC_0000001103710988"></a>
# IPC & RPC Development Guidelines
## When to Use<a name="section18502174174019"></a>
## 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<a name="section1633115419401"></a>
**Table 1** Native IPC APIs
## Available APIs
| Class/Interface | Function | Description |
| --------------- | -------- | ----------- |
| [IRemoteBroker](../reference/apis/js-apis-rpc.md#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. |
Table 1 Native IPC APIs
## How to Develop<a name="section4207112818418"></a>
| Class| API| Description|
| -------- | -------- | -------- |
| [IRemoteBroker](../reference/apis/js-apis-rpc.md#iremotebroker) | sptr&lt;IRemoteObject&gt; AsObject() | Holder of a remote proxy object. If you call this API on the stub, the **RemoteObject** is returned; if you call this API on the proxy, the proxy object is returned.|
| IRemoteStub | virtual int OnRemoteRequest(uint32_t code, MessageParcel &amp;data, MessageParcel &amp;reply, MessageOption &amp;option) | Callback used to process a request from the proxy and return the result. Derived classes need to override this API.|
| IRemoteProxy | | Service proxy class, which is derived from the **IRemoteProxy** class.|
**Using Native APIs**
1. Define the IPC interface **ITestAbility**.
## How to Develop
**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.
### **Using Native APIs**
```
class ITestAbility : public IRemoteBroker {
public:
1. Add dependencies.
SDK dependency:
```
#IPC scenario
external_deps = [
"ipc:ipc_single",
]
#RPC scenario
external_deps = [
"ipc:ipc_core",
]
```
In addition, the refbase implementation on which IPC/RPC depends is stored in **//utils**. Add the dependency on the Utils source code.
```
external_deps = [
"c_utils:utils",
]
```
2. 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.
```c++
#include "iremote_broker.h"
// Define message codes.
const int TRANS_ID_PING_ABILITY = 5
const std::string DESCRIPTOR = "test.ITestAbility";
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.
DECLARE_INTERFACE_DESCRIPTOR(to_utf16(DESCRIPTOR));
virtual int TestPingAbility(const std::u16string &dummy) = 0; // Define functions.
};
```
};
```
2. Define and implement service provider **TestAbilityStub**.
3. Define and implement service provider **TestAbilityStub**.
This 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.
This class is related to the IPC framework and needs to inherit **IRemoteStub&lt;ITestAbility&gt;**. You need to override **OnRemoteRequest** on the stub to receive requests from the proxy.
```
class TestAbilityStub : public IRemoteStub<ITestAbility> {
public:
virtual int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override;
int TestPingAbility(const std::u16string &dummy) override;
```c++
#include "iability_test.h"
#include "iremote_stub.h"
class TestAbilityStub : public IRemoteStub<ITestAbility> {
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<ITestAbility\>**. You can call **SendRequest** to send a request to the stub and expose the capabilities provided by the stub.
```
class TestAbilityProxy : public IRemoteProxy<ITestAbility> {
public:
explicit TestAbilityProxy(const sptr<IRemoteObject> &impl);
int TestPingService(const std::u16string &dummy) override;
private:
static inline BrokerDelegator<TestAbilityProxy> delegator_; // Use the iface_cast macro.
}
TestAbilityProxy::TestAbilityProxy(const sptr<IRemoteObject> &impl)
: IRemoteProxy<ITestAbility>(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<ISystemAbilityManager> samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
sptr<IRemoteObject> remoteObject = samgr->GetSystemAbility(saId);
sptr<ITestAbility> testAbility = iface_cast<ITestAbility>(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<ISystemAbilityManager> samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
sptr<IRemoteObject> remoteObject = samgr->GetSystemAbility(saId, deviceId); // deviceId identifies a device.
sptr<TestAbilityProxy> proxy(new TestAbilityProxy(remoteObject)); // Construct a proxy.
```
int TestAbilityStub::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);
}
}
```
4. Define the **TestAbility** class that implements functions for the stub.
```c++
#include "iability_server_test.h"
class TestAbility : public TestAbilityStub {
public:
int TestPingAbility(const std::u16string &dummy);
}
int TestAbility::TestPingAbility(const std::u16string &dummy) {
return 0;
}
```
5. Define and implement **TestAbilityProxy**.
This class is implemented on the proxy and inherits **IRemoteProxy&lt;ITestAbility&gt;**. You can call **SendRequest** to send a request to the stub and expose the capabilities provided by the stub.
```c++
#include "iability_test.h"
#include "iremote_proxy.h"
#include "iremote_object.h"
class TestAbilityProxy : public IRemoteProxy<ITestAbility> {
public:
explicit TestAbilityProxy(const sptr<IRemoteObject> &impl);
int TestPingAbility(const std::u16string &dummy) override;
private:
static inline BrokerDelegator<TestAbilityProxy> delegator_; // Use the iface_cast macro.
}
TestAbilityProxy::TestAbilityProxy(const sptr<IRemoteObject> &impl)
: IRemoteProxy<ITestAbility>(impl)
{
}
int TestAbilityProxy::TestPingAbility(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;
}
```
6. 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.
```c++
// 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);
```
7. Obtain the SA.
Call the **GetSystemAbility** function of the **SystemAbilityManager** class to obtain the **IRemoteObject** for the SA, and create a **TestAbilityProxy** instance.
```c++
// Obtain the proxy of the SA registered on the local device.
sptr<ISystemAbilityManager> samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
sptr<IRemoteObject> remoteObject = samgr->GetSystemAbility(saId);
sptr<ITestAbility> testAbility = iface_cast<ITestAbility>(remoteObject); // Use the iface_cast macro to convert the proxy to a specific type.
// Obtain the proxy of the SA registered with any other devices.
sptr<ISystemAbilityManager> samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
// networkId is the device identifier and can be obtained through GetLocalNodeDeviceInfo.
sptr<IRemoteObject> remoteObject = samgr->GetSystemAbility(saId, networkId);
sptr<TestAbilityProxy> proxy(new TestAbilityProxy(remoteObject)); // Construct a proxy.
```
### **Using JS APIs**
1. Add dependencies.
```ts
import rpc from "@ohos.rpc"
import featureAbility from "@ohos.ability.featureAbility"
```
2. Bind the desired ability.
Construct the **want** variable, and specify the bundle name and component name of the application where the ability is located. If cross-device communication is involved, also specify the network ID of the target device, which can be obtained through **deviceManager**. Then, construct the **connect** variable, and specify the callback that is called when the binding is successful, the binding fails, or the ability is disconnected. After that, call the API provided by **featureAbility** to bind an ability.
```ts
import rpc from "@ohos.rpc"
import featureAbility from "@ohos.ability.featureAbility"
let proxy = null
let connectId = null
// Bind the ability on a single device.
let want = {
// Enter the bundle name and ability name.
"bundleName": "ohos.rpc.test.server",
"abilityName": "ohos.rpc.test.server.ServiceAbility",
}
let connect = {
onConnect:function(elementName, remote) {
proxy = remote
},
onDisconnect:function(elementName) {
},
onFailed:function() {
proxy = null
}
}
connectId = featureAbility.connectAbility(want, connect)
// If you're binding the ability across devices, use deviceManager to obtain the network ID of the target device.
import deviceManager from '@ohos.distributedHardware.deviceManager'
function deviceManagerCallback(deviceManager) {
let deviceList = deviceManager.getTrustedDeviceListSync()
let networkId = deviceList[0].networkId
let want = {
"bundleName": "ohos.rpc.test.server",
"abilityName": "ohos.rpc.test.service.ServiceAbility",
"networkId": networkId,
"flags": 256
}
connectId = featureAbility.connectAbility(want, connect)
}
// The first parameter specifies the bundle name of the application, and the second parameter specifies the callback used to return the device ID obtained by using DeviceManager.
deviceManager.createDeviceManager("ohos.rpc.test", deviceManagerCallback)
```
3. Process requests sent from the client.
Call the **onConnect** API to return a proxy object inherited from **rpc.RemoteObject** after the ability is successfully bound. Implement the **onRemoteMessageRequest** API for the proxy object to process requests sent from the client.
```ts
onConnect(want: Want) {
var robj:rpc.RemoteObject = new Stub("rpcTestAbility")
return robj
}
class Stub extends rpc.RemoteObject {
constructor(descriptor) {
super(descriptor)
}
onRemoteMessageRequest(code, data, reply, option) {
// Process requests sent from the client based on the code.
return true
}
}
```
4. Process responses sent from the server.
Obtain the proxy object from the **onConnect** callback, call **sendRequestAsync** to send a request, and receive the response using a callback or a promise (an object representing the eventual completion or failure of an asynchronous operation and its result value).
```ts
// Use a promise.
let option = new rpc.MessageOption()
let data = rpc.MessageParcel.create()
let reply = rpc.MessageParcel.create()
// Write parameters to data.
proxy.sendRequestAsync(1, data, reply, option)
.then(function(result) {
if (result.errCode != 0) {
console.error("send request failed, errCode: " + result.errCode)
return
}
// Read the result from result.reply.
})
.catch(function(e) {
console.error("send request got exception: " + e)
}
.finally(() => {
data.reclaim()
reply.reclaim()
})
// Use a callback.
function sendRequestCallback(result) {
try {
if (result.errCode != 0) {
console.error("send request failed, errCode: " + result.errCode)
return
}
// Read the result from result.reply.
} finally {
result.data.reclaim()
result.reply.reclaim()
}
}
let option = new rpc.MessageOption()
let data = rpc.MessageParcel.create()
let reply = rpc.MessageParcel.create()
// Write parameters to data.
proxy.sendRequest(1, data, reply, option, sendRequestCallback)
```
5. Tear down the connection.
Use the API provided by **featureAbility** to tear down the connection when the communication is over.
```ts
import rpc from "@ohos.rpc"
import featureAbility from "@ohos.ability.featureAbility"
function disconnectCallback() {
console.info("disconnect ability done")
}
featureAbility.disconnectAbility(connectId, disconnectCallback)
```
......@@ -3,20 +3,42 @@
## Basic Concepts
Inter-process communication (IPC) and remote procedure call (RPC) are used to implement cross-process communication. IPC uses the Binder driver to implement inter-process communication within a device, whereas RPC uses the intelligent software bus driver to implement inter-process communication across devices.
The 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 the client-server model for communication. The client (service requester) obtains the proxy of the server (service provider) and uses this proxy to read and write data. The server registers system abilities (SAs) with the system ability manager (SAMgr), which manages the SAs and provides interfaces for clients. To interact with an SA, the client must obtain the proxy of the SA from SAMgr.
The reason why cross-process communication is needed is that each process has its own independent resources and memory space and one process is not allowed to access the resources and memory space of other processes. IPC and RPC usually use the client-server model, where the client (service requester, that is, the process that requests a service) obtains the proxy of the server (service provider, that is, the process that provides the service) and uses the proxy to read and write data to implement data communication across processes. More specifically, the client constructs a proxy object of the server. The proxy object has the same functions as the server. To access a certain API of the server, you only need to access the corresponding API in the proxy object. The proxy object sends the request to the server, and the server processes the received request and returns the processing result to the proxy object through the driver. Then, the proxy object forwards the processing result to the client. The server registers system abilities (SAs) with the system ability manager (SAMgr), which manages the SAs and provides APIs for clients. To communicate with a specific SA, the client must obtain the proxy of the SA from SAMgr.
In OpenHarmony documents, proxy represents the service requester, and stub represents the service provider.
In the following sections, proxy represents the service requester, and stub represents the service provider.
![IPC&RPC communication mechanisms](figures/IPC_RPC_communication.PNG)
## Constraints
- The data transmitted for inter-process communication within a device cannot exceed 1 MB. If more data needs to be transmitted, use the anonymous shared memory.
- During cross-process communication within a single device, the maximum amount of data to be transmitted is about 1 MB. If the amount of data to be transmitted exceeds this limit, use the [anonymous shared memory](https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-rpc.md#ashmem8).
- Subscription to death notifications of anonymous stub objects (not registered with SAMgr) is prohibited in RPC.
- During cross-process communication across processes, a proxy object cannot be passed back to the device that hosts the stub object pointed by the proxy object. That is, the proxy object pointing to the stub object of the remote device cannot be passed across processes twice on the local device.
## **Recommendations**
First, compile an API class and define message codes in the API class for both communication parties to identify operations. Unimplemented APIs are allowed in the API class because it must be inherited by both communication parties and its inheritance classes cannot be abstract classes. When inheriting the API class, both communication parties must implement the unimplemented APIs, so as to make sure that the inheritance classes are not abstract classes.
Then, implement the API class specific to the stub, and override the **AsObject** and **OnRemoteRequest** APIs. In addition, compile the proxy to implement the APIs in the API class and override the **AsObject** API. You can also encapsulate an additional API for calling **SendRequest** to send data to the peer.
After the preceding operations are done, register a system ability (SA) with SAMgr. Note that the registration should be completed in the process that hosts the stub. Then, obtain the proxy from SAMgr as needed to implement cross-process communication with the stub.
Related steps are as follows:
- Implementing the API class: Inherit **IRemoteBroker**, define message codes, and declare APIs that are not implemented in the API class.
- Implementing the service provider (stub): Inherit **IRemoteStub** or **RemoteObject**, and override the **AsObject** and **OnRemoteRequest** APIs.
- Implementing the service requester (proxy): Inherit **IRemoteProxy** or **RemoteProxy**, override the **AsObject** API, and encapsulate the required API to call **SendRequest**.
- Registering the SA: Apply for a unique ID for the SA, and register the SA with SAMgr.
- The cross-device proxy object cannot be passed to the device hosting the stub object pointed by this proxy object.
- Obtaining the SA: Obtain the proxy based on the SA ID and device ID, and use the proxy to communicate with the remote end.
## Related Modules
[Distributed Scheduler](https://gitee.com/openharmony/ability_dmsfwk)
[Distributed Ability Manager Service Framework](https://gitee.com/openharmony/ability_dmsfwk)
# Subscribing to State Changes of a Remote Object
IPC/RPC allows you to subscribe to the state changes of a remote stub object. When the remote stub object dies, a death notification will be sent to your local proxy object. Such subscription and unsubscription are controlled by APIs. To be specific, you need to implement the **DeathRecipient** callback and the **onRemoteDied** method to clear resources. This callback is invoked when the process accommodating the remote stub object dies, or the device accommodating the remote stub object leaves the network.
IPC/RPC allows you to subscribe to the state changes of a remote stub object. When the remote stub object dies, a death notification will be sent to your local proxy object. Such subscription and unsubscription are controlled by APIs. To be specific, you need to implement the **DeathRecipient** interface and the **onRemoteDied** API to clear resources. This callback is invoked when the process accommodating the remote stub object dies, or the device accommodating the remote stub object leaves the network. It is worth noting that these APIs should be called in the following order: The proxy object must first subscribe to death notifications of the stub object. If the stub object is in the normal state, the proxy object can cancel the subscription as required. If the process of the stub object exits or the device hosting the stub object goes offline, subsequent operations customized by the proxy object will be automatically triggered.
Note that the proxy object must first subscribe to death notifications of the stub object. If the stub object is in the normal state, the proxy object can cancel the subscription as required. If the process of the stub object exits or the device hosting the stub object goes offline, subsequent operations customized by the proxy object will be automatically triggered.
## When to Use
This subscription mechanism is applicable when the local proxy object needs to detect death of the process hosting the remote stub object or network detach of the device hosting the remote stub object. When the proxy detects death of the remote stub object, the proxy can clear local resources. Currently, IPC supports death notification for anonymous objects, but RPC does not. That is, you can only subscribe to death notifications of services that have been registered with SAMgr.
## **Using Native APIs**
## **Development Using Native APIs**
| API| Return Value Type| Feature Description|
| -------- | -------- | -------- |
| AddDeathRecipient(const sptr\<DeathRecipient> &recipient); | bool | Adds a recipient for death notifications of a remote stub object.|
| RemoveDeathRecipient(const sptr\<DeathRecipient> &recipient); | bool | Removes the recipient for death notifications of a remote stub object.|
| OnRemoteDied(const wptr\<IRemoteObject> &object); | void | Called when the remote stub object dies.|
| API| Description|
| -------- | -------- |
| AddDeathRecipient(const sptr\<DeathRecipient> &recipient); | Adds a recipient for death notifications of a remote stub object.|
| RemoveDeathRecipient(const sptr\<DeathRecipient> &recipient); | Removes the recipient for death notifications of a remote stub object.|
| OnRemoteDied(const wptr\<IRemoteObject> &object); | Called when the remote stub object dies.|
### Sample Code
```C++
#include "iremote_broker.h"
#include "iremote_stub.h"
## Sample Code
// Define message codes.
enum {
TRANS_ID_PING_ABILITY = 5,
TRANS_ID_REVERSED_MONITOR
};
const std::string DESCRIPTOR = "test.ITestAbility";
class ITestService : public IRemoteBroker {
public:
// DECLARE_INTERFACE_DESCRIPTOR is mandatory, and the input parameter is std::u16string.
DECLARE_INTERFACE_DESCRIPTOR(to_utf16(DESCRIPTOR));
virtual int TestPingAbility(const std::u16string &dummy) = 0; // Define functions.
};
class TestServiceProxy : public IRemoteProxy<ITestAbility> {
public:
explicit TestAbilityProxy(const sptr<IRemoteObject> &impl);
virtual int TestPingAbility(const std::u16string &dummy) override;
int TestAnonymousStub();
private:
static inline BrokerDelegator<TestAbilityProxy> delegator_; // Use the iface_cast macro.
};
TestServiceProxy::TestServiceProxy(const sptr<IRemoteObject> &impl)
: IRemoteProxy<ITestAbility>(impl)
{
}
int TestServiceProxy::TestPingAbility(const std::u16string &dummy){
MessageOption option;
MessageParcel dataParcel, replyParcel;
dataParcel.WriteString16(dummy);
int error = PeerHolder::Remote()->SendRequest(TRANS_ID_PING_ABILITY, dataParcel, replyParcel, option);
int result = (error == ERR_NONE) ? replyParcel.ReadInt32() : -1;
return result;
}
```
```c++
#include "iremote_object.h"
class TestDeathRecipient : public IRemoteObject::DeathRecipient {
public:
virtual void OnRemoteDied(const wptr<IRemoteObject>& remoteObject);
}
void TestDeathRecipient::OnRemoteDied(const wptr<IRemoteObject>& remoteObject)
{
}
```
```c++
sptr<IPCObjectProxy> object = new IPCObjectProxy(1, to_utf16(DESCRIPTOR));
sptr<IRemoteObject::DeathRecipient> deathRecipient (new TestDeathRecipient());// Construct a death notification recipient.
bool result = proxy->AddDeathRecipient(deathRecipient); // Add a recipient for death notifications.
result = proxy->RemoveDeathRecipient(deathRecipient); // Remove the recipient for death notifications.
bool result = object->AddDeathRecipient(deathRecipient); // Add a recipient for death notifications.
result = object->RemoveDeathRecipient(deathRecipient); // Remove the recipient for death notifications.
```
## **Using JS APIs**
| API | Return Value Type| Feature Description |
| -------------------- | ---------- | ------------------------------------------------------------ |
| addDeathRecippient | boolean | Adds a recipient for death notifications of the remote object, including death notifications of the remote proxy.|
| removeDeathRecipient | boolean | Removes the recipient for death notifications of the remote object. |
| onRemoteDied | void | Called to perform subsequent operations when a death notification of the remote object is received.|
### Sample Code
```ts
import FA from "@ohos.ability.featureAbility";
let proxy;
let connect = {
onConnect: function(elementName, remoteProxy) {
console.log("RpcClient: js onConnect called.");
proxy = remoteProxy;
},
onDisconnect: function(elementName) {
console.log("RpcClient: onDisconnect");
},
onFailed: function() {
console.log("RpcClient: onFailed");
}
};
let want = {
"bundleName": "com.ohos.server",
"abilityName": "com.ohos.server.EntryAbility",
};
FA.connectAbility(want, connect);
class MyDeathRecipient {
onRemoteDied() {
console.log("server died");
}
}
let deathRecipient = new MyDeathRecipient();
proxy.addDeathRecippient(deathRecipient, 0);
proxy.removeDeathRecipient(deathRecipient, 0);
```
## Reverse Death Notification (Anonymous Stub)
Forward dead notification is a mechanism that allows the proxy to detect death notifications of the stub. To achieve reverse dead notification, we can leverage the forward dead notification mechanism to allow the stub to detect death notifications of the proxy.
Suppose there are two processes, A (the process hosting the original stub) and B (the process hosting the original proxy). After obtaining the proxy object of process A, process B creates an anonymous stub object (that is, a stub object not registered with SAMgr), which can be called a callback stub. Then, process B calls **SendRequest** to send the callback stub to the original stub of process A. As a result, process A obtains the callback proxy of process B. When process B dies or the device hosting process B detaches from the network, the callback stub dies. The callback proxy detects the death of the callback stub and sends a death notification to the original stub. In this way, reverse death notification is implemented.
> NOTE
> - Reverse death notification can only be used for cross-process communication within a device.
> - When an anonymous stub object is not pointed by any proxy, the kernel automatically reclaims the object.
### Sample Code
```c++
// Proxy
int TestAbilityProxy::TestAnonymousStub()
{
MessageOption option;
MessageParcel dataParcel, replyParcel;
dataParcel.UpdateDataVersion(Remote());
dataParcel.WriteRemoteObject(new TestAbilityStub());
int error = Remote()->SendRequest(TRANS_ID_REVERSED_MONITOR,dataParcel, replyParcel, option);
int result = (error == ERR_NONE) ? replyParcel.ReadInt32() : -1;
return result;
}
// Stub
int TestAbilityStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)
{
switch (code) {
case TRANS_ID_REVERSED_MONITOR: {
sptr<IRemoteObject> obj = data.ReadRemoteObject();
if (obj == nullptr) {
reply.WriteInt32(ERR_NULL_OBJECT);
return ERR_NULL_OBJECT;
}
bool result = obj->AddDeathRecipient(new TestDeathRecipient());
result ? reply.WriteInt32(ERR_NONE) : reply.WriteInt32(-1);
break;
}
default:
break;
}
return ERR_NONE;
}
```
......@@ -40,8 +40,8 @@ try {
// 1. Obtain the list of input devices and check whether a physical keyboard is connected.
inputDevice.getDeviceList().then(data => {
for (let i = 0; i < data.length; ++i) {
inputDevice.getKeyboardType(data[i]).then(res => {
if (type == inputDevice.KeyboardType.ALPHABETIC_KEYBOARD) {
inputDevice.getKeyboardType(data[i]).then(type => {
if (type === inputDevice.KeyboardType.ALPHABETIC_KEYBOARD) {
// The physical keyboard is connected.
isPhysicalKeyboardExist = true;
}
......@@ -53,7 +53,7 @@ try {
console.log(`Device event info: ${JSON.stringify(data)}`);
inputDevice.getKeyboardType(data.deviceId, (error, type) => {
console.log("The keyboard type is: " + type);
if (type == inputDevice.KeyboardType.ALPHABETIC_KEYBOARD && data.type == 'add') {
if (type === inputDevice.KeyboardType.ALPHABETIC_KEYBOARD && data.type == 'add') {
// The physical keyboard is inserted.
isPhysicalKeyboardExist = true;
} else if (type == inputDevice.KeyboardType.ALPHABETIC_KEYBOARD && data.type == 'remove') {
......
......@@ -7,7 +7,7 @@ Mouse pointer management provides the functions such as displaying or hiding the
## Modules to Import
```js
import inputDevice from '@ohos.multimodalInput.pointer';
import pointer from '@ohos.multimodalInput.pointer';
```
## Available APIs
......
# @ohos.brightness
# @ohos.brightness (Screen Brightness)
The **brightness** module provides an API for setting the screen brightness.
......
# @ohos.hiSysEvent
# @ohos.hiSysEvent (System Event Logging)
The **hiSysEvent** module provides the system event logging functions, such as configuring trace points, subscribing to system events, and querying system events written to the event file.
......
# @ohos.hiTraceChain
# @ohos.hiTraceChain (Distributed Call Chain Tracing)
The **hiTraceChain** module implements call chain tracing throughout a service process. It provides functions such as starting and stopping call chain tracing and configuring trace points.
......
# @ohos.hiTraceMeter
# @ohos.hiTraceMeter (Performance Tracing)
The **hiTraceMeter** module provides the functions of tracing service processes and monitoring the system performance. It provides the data needed for hiTraceMeter to carry out performance analysis.
......
......@@ -8,7 +8,7 @@ The **mouseEvent** module provides mouse events reported by an input device.
## Modules to Import
```js
import {Action,Button,Axis,AxisValue,MouseEvent} from '@ohos.multimodalInput.mouseEvent';
import { Action, Button, Axis, AxisValue, MouseEvent } from '@ohos.multimodalInput.mouseEvent';
```
## Action
......
......@@ -275,7 +275,7 @@ import window from '@ohos.window';
window.getTopWindow((error, win) => {
win.getProperties((error, properties) => {
var windowId = properties.id;
let windowId = properties.id;
if (windowId < 0) {
console.log(`Invalid windowId`);
return;
......@@ -318,7 +318,7 @@ import window from '@ohos.window';
window.getTopWindow((error, win) => {
win.getProperties((error, properties) => {
var windowId = properties.id;
let windowId = properties.id;
if (windowId < 0) {
console.log(`Invalid windowId`);
return;
......@@ -357,7 +357,7 @@ import window from '@ohos.window';
window.getTopWindow((error, win) => {
win.getProperties((error, properties) => {
var windowId = properties.id;
let windowId = properties.id;
if (windowId < 0) {
console.log(`Invalid windowId`);
return;
......@@ -395,7 +395,7 @@ import window from '@ohos.window';
window.getTopWindow((error, win) => {
win.getProperties((error, properties) => {
var windowId = properties.id;
let windowId = properties.id;
if (windowId < 0) {
console.log(`Invalid windowId`);
return;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册