You need to sign in or sign up before continuing.
未验证 提交 6cb42a52 编写于 作者: O openharmony_ci 提交者: Gitee

!18433 翻译已完成16931+15868+17718+17508+17817+17974+17925+18000

Merge pull request !18433 from shawn_he/15868-d
...@@ -158,5 +158,4 @@ httpRequest.request2( ...@@ -158,5 +158,4 @@ httpRequest.request2(
httpRequest.destroy(); httpRequest.destroy();
} }
); );
``` ```
\ No newline at end of file
...@@ -81,7 +81,7 @@ For the complete list of APIs and example code, see [Network Connection Manageme ...@@ -81,7 +81,7 @@ For the complete list of APIs and example code, see [Network Connection Manageme
6. Call **conn.unregister()** to unsubscribe from the network status changes if required. 6. Call **conn.unregister()** to unsubscribe from the network status changes if required.
```js ```js
// Import the connection namespace. // Import the connection namespace.
import connection from '@ohos.net.connection' import connection from '@ohos.net.connection'
let netCap = { let netCap = {
...@@ -128,7 +128,7 @@ conn.unregister((err, data) => { ...@@ -128,7 +128,7 @@ conn.unregister((err, data) => {
2. Call **getAllNets** to obtain the list of all connected networks. 2. Call **getAllNets** to obtain the list of all connected networks.
```js ```js
// Import the connection namespace. // Import the connection namespace.
import connection from '@ohos.net.connection' import connection from '@ohos.net.connection'
// Obtain the list of all connected networks. // Obtain the list of all connected networks.
...@@ -154,7 +154,7 @@ connection.getAllNets((err, data) => { ...@@ -154,7 +154,7 @@ connection.getAllNets((err, data) => {
4. Call **getConnectionProperties** to obtain the connection information of the data network specified by **NetHandle**. 4. Call **getConnectionProperties** to obtain the connection information of the data network specified by **NetHandle**.
```js ```js
// Import the connection namespace. // Import the connection namespace.
import connection from '@ohos.net.connection' import connection from '@ohos.net.connection'
// Call getDefaultNet to obtain the default data network specified by **NetHandle**. // Call getDefaultNet to obtain the default data network specified by **NetHandle**.
......
...@@ -44,7 +44,7 @@ For the complete list of APIs and example code, see [Ethernet Connection](../ref ...@@ -44,7 +44,7 @@ For the complete list of APIs and example code, see [Ethernet Connection](../ref
5. Call **getIfaceConfig** in user mode to obtain the static network attributes of the **eth0** port. By default, an unconfigured Ethernet network uses the DHCP mode, in which the Ethernet network obtains the automatically assigned network attributes. 5. Call **getIfaceConfig** in user mode to obtain the static network attributes of the **eth0** port. By default, an unconfigured Ethernet network uses the DHCP mode, in which the Ethernet network obtains the automatically assigned network attributes.
```js ```js
// Import the ethernet namespace from @ohos.net.ethernet. // Import the ethernet namespace from @ohos.net.ethernet.
import ethernet from '@ohos.net.ethernet' import ethernet from '@ohos.net.ethernet'
// Call getAllActiveIfaces to obtain the list of all active network ports. // Call getAllActiveIfaces to obtain the list of all active network ports.
...@@ -96,7 +96,7 @@ ethernet.getIfaceConfig("eth0", (error, data) => { ...@@ -96,7 +96,7 @@ ethernet.getIfaceConfig("eth0", (error, data) => {
6. Call **getIfaceConfig** in user mode to obtain the static network attributes of the **eth0** port. 6. Call **getIfaceConfig** in user mode to obtain the static network attributes of the **eth0** port.
```js ```js
// Import the ethernet namespace from @ohos.net.ethernet. // Import the ethernet namespace from @ohos.net.ethernet.
import ethernet from '@ohos.net.ethernet' import ethernet from '@ohos.net.ethernet'
// Call getAllActiveIfaces to obtain the list of all active network ports. // Call getAllActiveIfaces to obtain the list of all active network ports.
...@@ -158,13 +158,13 @@ ethernet.getIfaceConfig("eth0", (error, data) => { ...@@ -158,13 +158,13 @@ ethernet.getIfaceConfig("eth0", (error, data) => {
4. Call the **off()** method to unsubscribe from **interfaceStateChange** events. 4. Call the **off()** method to unsubscribe from **interfaceStateChange** events.
```js ```js
// Import the ethernet namespace from @ohos.net.ethernet. // Import the ethernet namespace from @ohos.net.ethernet.
import ethernet from '@ohos.net.ethernet' import ethernet from '@ohos.net.ethernet'
// Subscribe to interfaceStateChange events. // Subscribe to interfaceStateChange events.
ethernet.on('interfaceStateChange', ((data) => { ethernet.on('interfaceStateChange', (data) => {
console.log(JSON.stringify(data)); console.log(JSON.stringify(data));
})); });
// Unsubscribe from interfaceStateChange events. // Unsubscribe from interfaceStateChange events.
ethernet.off('interfaceStateChange'); ethernet.off('interfaceStateChange');
......
...@@ -60,7 +60,7 @@ For the complete list of APIs and example code, see [Network Sharing](../referen ...@@ -60,7 +60,7 @@ For the complete list of APIs and example code, see [Network Sharing](../referen
4. Return the callback for successfully starting network sharing. 4. Return the callback for successfully starting network sharing.
```js ```js
// Import the sharing namespace from @ohos.net.sharing. // Import the sharing namespace from @ohos.net.sharing.
import sharing from '@ohos.net.sharing' import sharing from '@ohos.net.sharing'
// Subscribe to network sharing state changes. // Subscribe to network sharing state changes.
...@@ -85,7 +85,7 @@ sharing.startSharing(sharing.SharingIfaceType.SHARING_WIFI, (error) => { ...@@ -85,7 +85,7 @@ sharing.startSharing(sharing.SharingIfaceType.SHARING_WIFI, (error) => {
4. Return the callback for successfully stopping network sharing. 4. Return the callback for successfully stopping network sharing.
```js ```js
// Import the sharing namespace from @ohos.net.sharing. // Import the sharing namespace from @ohos.net.sharing.
import sharing from '@ohos.net.sharing' import sharing from '@ohos.net.sharing'
// Subscribe to network sharing state changes. // Subscribe to network sharing state changes.
...@@ -110,7 +110,7 @@ sharing.stopSharing(sharing.SharingIfaceType.SHARING_WIFI, (error) => { ...@@ -110,7 +110,7 @@ sharing.stopSharing(sharing.SharingIfaceType.SHARING_WIFI, (error) => {
4. Call **stopSharing** to stop network sharing of the specified type and clear the data volume of network sharing. 4. Call **stopSharing** to stop network sharing of the specified type and clear the data volume of network sharing.
```js ```js
// Import the sharing namespace from @ohos.net.sharing. // Import the sharing namespace from @ohos.net.sharing.
import sharing from '@ohos.net.sharing' import sharing from '@ohos.net.sharing'
// Call startSharing to start network sharing of the specified type. // Call startSharing to start network sharing of the specified type.
......
...@@ -87,37 +87,37 @@ The implementation is similar for UDP Socket and TCP Socket connections. The fol ...@@ -87,37 +87,37 @@ The implementation is similar for UDP Socket and TCP Socket connections. The fol
7. Enable the TCP Socket connection to be automatically closed after use. 7. Enable the TCP Socket connection to be automatically closed after use.
```js ```js
import socket from '@ohos.net.socket' import socket from '@ohos.net.socket'
// Create a TCPSocket object. // Create a TCPSocket object.
let tcp = socket.constructTCPSocketInstance(); let tcp = socket.constructTCPSocketInstance();
// Subscribe to TCP Socket connection events. // Subscribe to TCP Socket connection events.
tcp.on('message', value => { tcp.on('message', value => {
console.log("on message") console.log("on message")
let buffer = value.message let buffer = value.message
let dataView = new DataView(buffer) let dataView = new DataView(buffer)
let str = "" let str = ""
for (let i = 0;i < dataView.byteLength; ++i) { for (let i = 0; i < dataView.byteLength; ++i) {
str += String.fromCharCode(dataView.getUint8(i)) str += String.fromCharCode(dataView.getUint8(i))
} }
console.log("on connect received:" + str) console.log("on connect received:" + str)
}); });
tcp.on('connect', () => { tcp.on('connect', () => {
console.log("on connect") console.log("on connect")
}); });
tcp.on('close', () => { tcp.on('close', () => {
console.log("on close") console.log("on close")
}); });
// Bind the local IP address and port number. // Bind the local IP address and port number.
let bindAddress = { let bindAddress = {
address: '192.168.xx.xx', address: '192.168.xx.xx',
port: 1234, // Bound port, for example, 1234. port: 1234, // Bound port, for example, 1234.
family: 1 family: 1
}; };
tcp.bind(bindAddress, err => { tcp.bind(bindAddress, err => {
if (err) { if (err) {
console.log('bind fail'); console.log('bind fail');
return; return;
...@@ -150,18 +150,18 @@ The implementation is similar for UDP Socket and TCP Socket connections. The fol ...@@ -150,18 +150,18 @@ The implementation is similar for UDP Socket and TCP Socket connections. The fol
console.log('send success'); console.log('send success');
}) })
}); });
}); });
// Enable the TCP Socket connection to be automatically closed after use. Then, disable listening for TCP Socket connection events. // Enable the TCP Socket connection to be automatically closed after use. Then, disable listening for TCP Socket connection events.
setTimeout(() => { setTimeout(() => {
tcp.close((err) => { tcp.close((err) => {
console.log('close socket.') console.log('close socket.')
}); });
tcp.off('message'); tcp.off('message');
tcp.off('connect'); tcp.off('connect');
tcp.off('close'); tcp.off('close');
}, 30 * 1000); }, 30 * 1000);
``` ```
## Implementing Encrypted Data Transmission over TLS Socket Connections ## Implementing Encrypted Data Transmission over TLS Socket Connections
...@@ -184,7 +184,7 @@ TLS Socket connection process on the client: ...@@ -184,7 +184,7 @@ TLS Socket connection process on the client:
7. Enable the TLS Socket connection to be automatically closed after use. 7. Enable the TLS Socket connection to be automatically closed after use.
```js ```js
import socket from '@ohos.net.socket' import socket from '@ohos.net.socket'
// Create a TLS Socket connection (for two-way authentication). // Create a TLS Socket connection (for two-way authentication).
let tlsTwoWay = socket.constructTLSSocketInstance(); let tlsTwoWay = socket.constructTLSSocketInstance();
...@@ -208,7 +208,7 @@ tlsTwoWay.on('close', () => { ...@@ -208,7 +208,7 @@ tlsTwoWay.on('close', () => {
}); });
// Bind the local IP address and port number. // Bind the local IP address and port number.
tlsTwoWay.bind({address: '192.168.xxx.xxx', port: xxxx, family: 1}, err => { tlsTwoWay.bind({ address: '192.168.xxx.xxx', port: xxxx, family: 1 }, err => {
if (err) { if (err) {
console.log('bind fail'); console.log('bind fail');
return; return;
...@@ -280,7 +280,7 @@ tlsTwoWay.on('close', () => { ...@@ -280,7 +280,7 @@ tlsTwoWay.on('close', () => {
}); });
// Bind the local IP address and port number. // Bind the local IP address and port number.
tlsOneWay.bind({address: '192.168.xxx.xxx', port: xxxx, family: 1}, err => { tlsOneWay.bind({ address: '192.168.xxx.xxx', port: xxxx, family: 1 }, err => {
if (err) { if (err) {
console.log('bind fail'); console.log('bind fail');
return; return;
...@@ -319,3 +319,11 @@ tlsTwoWay.close((err) => { ...@@ -319,3 +319,11 @@ tlsTwoWay.close((err) => {
tlsTwoWay.off('close'); tlsTwoWay.off('close');
}); });
``` ```
## Samples
The following samples are provided to help you better understand how to develop Socket connection features:
- [`Socket`: Socket Connection (ArkTS) (API9)] (https://gitee.com/openharmony/applications_app_samples/tree/master/code/BasicFeature/Connectivity/Socket)
- [UDP Socket (ArkTS) (API9)](https://gitee.com/openharmony/codelabs/tree/master/NetworkManagement/UdpDemoOH)
- [TCP Socket (ArkTS) (API9)](https://gitee.com/openharmony/codelabs/tree/master/NetworkManagement/TcpSocketDemo)
...@@ -37,12 +37,12 @@ The WebSocket connection function is mainly implemented by the WebSocket module. ...@@ -37,12 +37,12 @@ The WebSocket connection function is mainly implemented by the WebSocket module.
5. Close the WebSocket connection if it is no longer needed. 5. Close the WebSocket connection if it is no longer needed.
```js ```js
import webSocket from '@ohos.net.webSocket'; import webSocket from '@ohos.net.webSocket';
var defaultIpAddress = "ws://"; var defaultIpAddress = "ws://";
let ws = webSocket.createWebSocket(); let ws = webSocket.createWebSocket();
ws.on('open', (err, value) => { ws.on('open', (err, value) => {
console.log("on open, status:" + JSON.stringify(value)); console.log("on open, status:" + JSON.stringify(value));
// When receiving the on('open') event, the client can use the send() API to communicate with the server. // When receiving the on('open') event, the client can use the send() API to communicate with the server.
ws.send("Hello, server!", (err, value) => { ws.send("Hello, server!", (err, value) => {
...@@ -52,8 +52,8 @@ The WebSocket connection function is mainly implemented by the WebSocket module. ...@@ -52,8 +52,8 @@ The WebSocket connection function is mainly implemented by the WebSocket module.
console.log("Failed to send the message. Err:" + JSON.stringify(err)); console.log("Failed to send the message. Err:" + JSON.stringify(err));
} }
}); });
}); });
ws.on('message', (err, value) => { ws.on('message', (err, value) => {
console.log("on message, message:" + value); console.log("on message, message:" + value);
// When receiving the `bye` message (the actual message name may differ) from the server, the client proactively disconnects from the server. // When receiving the `bye` message (the actual message name may differ) from the server, the client proactively disconnects from the server.
if (value === 'bye') { if (value === 'bye') {
...@@ -65,18 +65,24 @@ The WebSocket connection function is mainly implemented by the WebSocket module. ...@@ -65,18 +65,24 @@ The WebSocket connection function is mainly implemented by the WebSocket module.
} }
}); });
} }
}); });
ws.on('close', (err, value) => { ws.on('close', (err, value) => {
console.log("on close, code is " + value.code + ", reason is " + value.reason); console.log("on close, code is " + value.code + ", reason is " + value.reason);
}); });
ws.on('error', (err) => { ws.on('error', (err) => {
console.log("on error, error:" + JSON.stringify(err)); console.log("on error, error:" + JSON.stringify(err));
}); });
ws.connect(defaultIpAddress, (err, value) => { ws.connect(defaultIpAddress, (err, value) => {
if (!err) { if (!err) {
console.log("Connected successfully"); console.log("Connected successfully");
} else { } else {
console.log("Connection failed. Err:" + JSON.stringify(err)); console.log("Connection failed. Err:" + JSON.stringify(err));
} }
}); });
``` ```
## Samples
The following samples are provided to help you better understand how to develop WebSocket connection features:
- [`WebSocket`: WebSocket (ArkTS) (API9)](https://gitee.com/openharmony/applications_app_samples/tree/master/code/BasicFeature/Connectivity/WebSocket)
...@@ -7,3 +7,6 @@ ...@@ -7,3 +7,6 @@
- Error Management - Error Management
- [Development of Error Manager](errormanager-guidelines.md) - [Development of Error Manager](errormanager-guidelines.md)
- [Development of Application Recovery](apprecovery-guidelines.md) - [Development of Application Recovery](apprecovery-guidelines.md)
- Log Management
- [Application Freeze (appfreeze) Log Analysis](appfreeze-guidelines.md)
- [Process Crash (cppcrash) Log Analysis](cppcrash-guidelines.md)
# Application Freeze (appfreeze) Log Analysis
## Introduction
Application freeze (appfreeze) means that an application does not respond to user operations (for example, clicking) within a given period of time. OpenHarmony provides a mechanism for detecting appfreeze faults and generates appfreeze logs for fault analysis.
> NOTE
>
> This guide applies only to applications in the stage model.
> Before using this guide, you must have basic knowledge about the JS applications, C++ program stacks, and application-related subsystems.
## How to Obtain
appfreeze log is a type of fault logs managed together with the native process crash, JS application crash, and system process crash logs . You can obtain the log in any of the following ways.
### Collecting Logs by Using Shell
appfreeze logs start with **appfreeze-** in **/data/log/faultlog/faultlogger/**.
The log files are named in the format of **appfreeze-application package name-application UID-time (seconds level)**.
![appfreeze_20230308145160](figures/appfreeze_20230308145160.png)
### Collecting Logs by Using DevEco Studio
DevEco Studio collects device fault logs and saves them to FaultLog.
The logs are displayed by the bundle name, fault, and time.
![appfreeze_20230308145161](figures/appfreeze_20230308145161.png)
### Collecting Logs by Using faultLogger APIs
The FaultLogger module provides APIs to query various fault information. For details, see [@ohos.faultLogger](../reference/apis/js-apis-faultLogger.md).
## appfreeze Detection
Currently, appfreeze detection supports the fault types listed in the following table.
| Fault Type| Description|
| -------- | -------- |
| THREAD_BLOCK_6S | The application main thread times out due to a suspension.|
| APPLICATION_BLOCK_INPUT | The user input response times out.|
| LIFECYCLE_TIMEOUT | Ability lifecycle switching times out.|
| APP_LIFECYCLE_TIMEOUT | Application lifecycle switching times out.|
### Application Main Thread Timeout
If this fault occurs, the main thread of the current application is suspended or too many tasks are executed, affecting task execution smoothness and experience.
Such a fault can be detected as follows: The watchdog thread of the application periodically inserts an activation detection subthread to the main thread and inserts a timeout reporting subthread to its own thread. If activation detection is not executed within 3 seconds, the THREAD_BLOCK_3S event is reported; if activation detection is not executed within 6 seconds, the THREAD_BLOCK_6S event is reported. The two events together form an appfreeze log. The following figure shows the working principle.
![appfreeze_20230308145163](figures/appfreeze_20230308145163.png)
### User Input Response Timeout
This fault affects user experience. If this fault occurs, the system does not respond to a click event within 10 seconds.
Such a fault can be detected as follows: When a user clicks a certain button of the application, the input system sends a click event to the application. If the input system does not receive a response from the application within 10 seconds, a fault event is reported. The following figure shows the working principle.
![appfreeze_20230308145162](figures/appfreeze_20230308145162.png)
### Lifecycle Switching Timeout
This fault refers to an ability lifecycle switching timeout (LIFECYCLE\_TIMEOUT) or an application lifecycle switching timeout (APP\_LIFECYCLE\_TIMEOUT).
The fault occurs during lifecycle switching and affects the switchover between abilities in the current application or the switchover between applications.
Such a fault can be detected as follows: Upon the start of a lifecycle switchover process, the main thread inserts a timeout task to the watchdog thread, and then removes the timeout task when the lifecycle switchover is complete. If the timeout duration expires, a fault event is reported.
![appfreeze_20230308145164](figures/appfreeze_20230308145164.png)
The timeout duration varies according to the lifecycle.
| Lifecycle| Timeout Duration|
| -------- | -------- |
| Load | 10s |
| Terminate | 10s |
| Connect | 3s |
| Disconnect | 0.5s |
| Foreground | 5s |
| Background | 3s |
## appfreeze Log Analysis
To identify the cause of appfreeze, analyze the appfreeze logs together with HiLog logs.
The following example uses main tread suspension as an example to illustrate how to conduct log analysis. You can treat other types of faults in a similar way.
appfreeze logs are divided into several parts, including header information, and general and specific information in the body.
### Log Header Information
| Field| Description|
| -------- | -------- |
| Reason | Reason why the application does not respond. For details, see [appfreeze Detection](#appfreeze-detection).|
| PID | PID of the failed process, which can be used to search for related process information in the log.|
| PACKAGE_NAME | Application package name.|
![appfreeze_20230310105865](figures/appfreeze_20230310105865.png)
### General Information in the Log Body
General information is present in all logs. It contains the fields listed in the following table. You can search for these fields to locate the related information in the log.
| Field| Description|
| -------- | -------- |
| EVENTNAME | One or more fault events that constitute the cause of main thread suspension.|
| TIMESTAMP | Time when the fault event reported. You can narrow down the time range for viewing HiLog logs based on the timeout duration described in [appfreeze Detection](#appfreeze-detection).|
| PID | PID of the failed process, which can be used with the timestamp and timeout duration to search for related process information in the log.|
| PACKAGE_NAME | Application package name.|
| MSG | Dump information or description of the fault.|
| OpenStacktraceCatcher | Stack trace information of the process.|
| BinderCatcher | Information about IPC calls between a process and other system processes, such as the call waiting time.|
| PeerBinder Stacktrace | Information about stack trace of the peer process.|
| cpuusage | CPU usage of the device.|
| memory | Memory usage of the process.|
The following is an example process stack of OpenStacktraceCatcher.
In this example, when the stack surface window sends events through IPC, the process is stuck in the IPC communication phase.
![appfreeze_20230310105869](figures/appfreeze_20230310105869.png)
Example BinderCatcher information:
In the following example, process 1561 sends an IPC request to process 685 but does not receive any response within 10 seconds.
![appfreeze_20230310105868](figures/appfreeze_20230310105868.png)
Example PeerBinder Stacktrace information:
The following example shows the stack information of process 685, which is suspended at the peer end.
![appfreeze_20230310105870](figures/appfreeze_20230310105870.png)
Example CPU usage information:
The following example shows the CPU usage information of the device.
![appfreeze_20230310105871](figures/appfreeze_20230310105871.png)
Example memory usage information:
The following example shows the memory usage information of the process.
![appfreeze_20230310105872](figures/appfreeze_20230310105872.png)
### Specific Information in the Log Body (Application Main Thread Timeout)
According to [Application Main Thread Timeout] (#application-main-thread-timeout), the log in which **Reason** is **THREAD\_BLOCK\_6S** consists of two parts: THREAD\_BLOCK\_3S and THREAD\_BLOCK\_6S. By comparing the two parts, you can determine whether the appfreeze is due to a suspension or an excess number of tasks.
THREAD\_BLOCK\_3S is followed by THREAD\_BLOCK\_6S in the log. You can use the **EVENTNAME** field to search for the locations of the two events in the log.
Both events contain the **MSG** field, which stores information about the processing queue of the main thread when the suspension occurs. Hence, you can view the status of the event processing queue of the main thread at the two time points.
The example log shows that the event carrying **05:06:18.145** in the low-priority queue is being processed, and it is present in both the THREAD_BLOCK_3S and THREAD_BLOCK_6S. This indicates that the main thread suspension is not caused by an excess number of tasks.
Because THREAD_BLOCK_6S indicates a main thread suspension, you only need to analyze the stack information of the main thread (the ID of the main thread is the same as the process ID). In the example log, the main thread stack is run in the JS through ArkUI and therefore it can be concluded that the suspension occurs in the JS. Because stack is present in both THREAD_BLOCK_3S and THREAD_BLOCK_6S in the same position, the JS suspension is not caused by an excess number of tasks.
THREAD_BLOCK_3S:
![appfreeze_20230310105866](figures/appfreeze_20230310105866.png)
THREAD_BLOCK_6S:
![appfreeze_20230310105867](figures/appfreeze_20230310105867.png)
Then, you can check for the code segment being executed on the application side based on the HiLog log.
Generally, you can view the [general information in the log body](#general-information-in-the-log-body) to check for the cause of the suspension, for example, IPC suspension, high CPU usage, memory leakage, or high memory usage.
### Specific Information in the Log Body (User Input Response Timeout)
If **Reason** is **APPLICATION\_BLOCK\_INPUT**, no response is received within 10 seconds after a user click.
You can find the event description in **MSG**.
For details, see [General Information in the Log Body](#general-information-in-the-log-body). Note that there is a high probability that the main thread is suspended in the case of no response to the user input. You can compare the stack and BinderCatcher information in two log records for further analysis. If there is no log record indicating a main thread suspension, a large number of other events may exist before the input event. This may not cause a main thread suspension but can probably result in no response to user input.
### Specific Information in the Log Body (Lifecycle Switching Timeout)
For a lifecycle switching timeout, **Reason** can be **LIFECYCLE\_TIMEOUT** or **APP\_LIFECYCLE\_TIMEOUT**.
**LIFECYCLE\_TIMEOUT** indicates a lifecycle switching timeout at the ability level, and **APP\_LIFECYCLE\_TIMEOUT** indicates a lifecycle switching timeout at the application level.
MSG indicates the lifecycle that encounters a timeout.
In this example, **LIFECYCLE\_TIMEOUT** indicates that the timeout occurs during switching of the ability to the background, and **APP\_LIFECYCLE\_TIMEOUT** indicates that the timeout occurs in the application termination phase. You can locate related HiLog logs according to the timeout duration described in [Lifecycle Switching Timeout] (#lifecycle-switching-timeout).
LIFECYCLE_TIMEOUT:
![appfreeze_20230310105873](figures/appfreeze_20230310105873.png)
APP_LIFECYCLE_TIMEOUT:
![appfreeze_20230310105874](figures/appfreeze_20230310105874.png)
For details about other log information, see [General Information in the Log Body](#general-information-in-the-log-body). Note that there is a high probability that the main thread is suspended during lifecycle switching. You can compare the stack and BinderCatcher information in two log records for further analysis.
...@@ -5,48 +5,29 @@ ...@@ -5,48 +5,29 @@
During application running, some unexpected behaviors are inevitable. For example, unprocessed exceptions and errors are thrown, and the call or running constraints of the recovery framework are violated. During application running, some unexpected behaviors are inevitable. For example, unprocessed exceptions and errors are thrown, and the call or running constraints of the recovery framework are violated.
Process exit is treated as the default exception handling method. However, if user data is generated during application use, process exit may interrupt user operations and cause data loss. Process exit is treated as the default exception handling method. However, if user data is generated during application use, process exit may interrupt user operations and cause data loss.
Application recovery helps to restore the application state and save temporary data upon next startup in the case of an abnormal process exit, thus providing more consistent user experience. The application state includes two parts, namely, the page stack of the and the data saved in **onSaveState**. In this way, application recovery APIs may help you save temporary data, restart an application after it exits, and restore its status and data, which deliver a better user experience.
In API version 9, application recovery is supported only for a single ability of the application developed using the stage model. Application state saving and automatic restart are performed when a JsError occurs. Currently, the APIs support only the development of an application that adopts the stage model, single process, and single ability.
In API version 10, application recovery is applicable to multiple abilities of an application developed using the stage model. Application state storage and restore are performed when an AppFreeze occurs. If an application is killed in control mode, the application state will be restored upon next startup.
## Available APIs ## Available APIs
The application recovery APIs are provided by the **appRecovery** module, which can be imported via **import**. For details, see [Development Example](#development-example). The application recovery APIs are provided by the **appRecovery** module, which can be imported via **import**. For details, see [Development Example](#development-example). This document describes behaviors of APIs in API version 9, and the content will update with changes.
### Available APIs ### Available APIs
| API | Description | | API | Description |
| ------------------------------------------------------------ | ---------------------------------------------------- | | ------------------------------------------------------------ | ---------------------------------------------------- |
| enableAppRecovery(restart?: RestartFlag, saveOccasion?: SaveOccasionFlag, saveMode?: SaveModeFlag) : void;<sup>9+</sup> | Enables application recovery. After this API is called, the first ability that is displayed when the application is started from the initiator can be restored.| | enableAppRecovery(restart?: RestartFlag, saveOccasion?: SaveOccasionFlag, saveMode?: SaveModeFlag) : void; | Enables the application recovery function.|
| saveAppState(): boolean;<sup>9+</sup> | Saves the state of the ability that supports recovery in the current application.| | saveAppState(): boolean; | Saves the ability status of an application. |
| restartApp(): void;<sup>9+</sup> | Restarts the current process and starts the ability specified by **setRestartWant**. If no ability is specified, a foreground ability that supports recovery is restarted.| | restartApp(): void; | Restarts the current process. If there is saved ability status, it will be passed to the **want** parameter's **wantParam** attribute of the **onCreate** lifecycle callback of the ability.|
| saveAppState(context?: UIAbilityContext): boolean;<sup>10+</sup> | Saves the ability state specified by **Context**.|
| setRestartWant(want: Want): void;<sup>10+</sup> | Sets the abilities to restart when **restartApp** is actively called and **RestartFlag** is not **NO_RESTART**. The abilities must be under the same bundle name and must be a **UiAbility**.|
No error will be thrown if the preceding APIs are used in the troubleshooting scenario. The following are some notes on API usage: The APIs are used for troubleshooting and do not return any exception. Therefore, you need to be familiar with when they are used.
**enableAppRecovery**: This API should be called during application initialization. For example, you can call this API in **onCreate** of **AbilityStage**. For details, see [Parameter Description](../reference/apis/js-apis-app-ability-appRecovery.md). **enableAppRecovery**: This API should be called during application initialization. For example, you can call this API in **onCreate** of **AbilityStage**. For details, see [Parameter Description](../reference/apis/js-apis-app-ability-appRecovery.md).
**saveAppState**: After this API is called, the recovery framework invokes **onSaveState** for all abilities that support recovery in the current process. If you choose to save data in **onSaveState**, the related data and ability page stack are persistently stored in the local cache of the application. To save data of the specified ability, you need to specify the context corresponding to that ability. **saveAppState**: After this API is called, the framework calls back **onSaveState** of the ability. If data saving is accepted in this API, relevant data and the page stack of the ability are persisted to the local cache of the application.
**setRestartWant**: This API specifies the ability to be restarted by **appRecovery**.
**restartApp**: After this API is called, the recovery framework kills the current process and restarts the ability specified by **setRestartWant**, with **APP_RECOVERY** set as the startup cause. In API version 9 and scenarios where an ability is not specified by **setRestartWant**, the last foreground ability that supports recovery is started. If the no foreground ability supports recovery, the application crashes. If a saved state is available for the restarted ability, the saved state is passed as the **wantParam** attribute in the **want** parameter of the ability's **onCreate** callback.
### Application State Management
Since API version 10, application recovery is not limited to automatic restart in the case of an exception. Therefore, you need to understand when the application will load the saved state.
If the last exit of an application is not initiated by a user and a saved state is available for recovery, the startup reason is set to **APP_RECOVERY** when the application is started by the user next time, and the recovery state of the application is cleared.
The application recovery status flag is set when **saveAppState** is actively or passively called. The flag is cleared when the application exits normally or the saved state is consumed. (A normal exit is usually triggered by pressing the back key or clearing recent tasks.)
![Application recovery status management](./figures/application_recovery_status_management.png)
### Application State Saving and Restore
API version 10 or later supports saving of the application state when an application is suspended. If a JsError occurs, **onSaveState** is called in the main thread. If an AppFreeze occurs, however, the main thread may be suspended, and therefore **onSaveState** is called in a non-main thread. The following figure shows the main service flow.
![Application recovery from the freezing state](./figures/application_recovery_from_freezing.png) **restartApp**: After this API is called, the framework kills the current application process and restarts the ability in the foreground, with **APP_RECOVERY** specified as the startup cause.
When the application is suspended, the callback is not executed in the JS thread. Therefore, you are advised not to use the imported dynamic Native library or access the **thread_local** object created by the main thread in the code of the **onSaveState** callback.
### Framework Fault Management ### Framework Fault Management
...@@ -59,7 +40,9 @@ Fault management is an important way for applications to deliver a better user e ...@@ -59,7 +40,9 @@ Fault management is an important way for applications to deliver a better user e
- Fault query is the process of calling APIs of [faultLogger](../reference/apis/js-apis-faultLogger.md) to obtain the fault information. - Fault query is the process of calling APIs of [faultLogger](../reference/apis/js-apis-faultLogger.md) to obtain the fault information.
The figure below does not illustrate the time when [faultLogger](../reference/apis/js-apis-faultLogger.md) is called. You can refer to the [LastExitReason](../reference/apis/js-apis-app-ability-abilityConstant.md#abilityconstantlastexitreason) passed during application initialization to determine whether to call [faultLogger](../reference/apis/js-apis-faultLogger.md) to query information about the previous fault. The figure below does not illustrate the time when [faultLogger](../reference/apis/js-apis-faultLogger.md) is called. You can refer to the [LastExitReason](../reference/apis/js-apis-app-ability-abilityConstant.md#abilityconstantlastexitreason) passed during application initialization to determine whether to call [faultLogger](../reference/apis/js-apis-faultLogger.md) to query information about the previous fault.
![Fault rectification process](./figures/fault_rectification.png) ![Fault rectification process](./figures/fault_rectification.png)
It is recommended that you call [errorManager](../reference/apis/js-apis-app-ability-errorManager.md) to handle the exception. After the processing is complete, you can call the **saveAppState** API and restart the application. It is recommended that you call [errorManager](../reference/apis/js-apis-app-ability-errorManager.md) to handle the exception. After the processing is complete, you can call the **saveAppState** API and restart the application.
If you do not register [ErrorObserver](../reference/apis/js-apis-inner-application-errorObserver.md) or enable application recovery, the application process will exit according to the default processing logic of the system. Users can restart the application from the home screen. If you do not register [ErrorObserver](../reference/apis/js-apis-inner-application-errorObserver.md) or enable application recovery, the application process will exit according to the default processing logic of the system. Users can restart the application from the home screen.
If you have enabled application recovery, the recovery framework first checks whether application state saving is supported and whether the application state saving is enabled. If so, the recovery framework invokes [onSaveState](../reference/apis/js-apis-app-ability-uiAbility.md#uiabilityonsavestate) of the [Ability](../reference/apis/js-apis-app-ability-uiAbility.md). Finally, the application is restarted. If you have enabled application recovery, the recovery framework first checks whether application state saving is supported and whether the application state saving is enabled. If so, the recovery framework invokes [onSaveState](../reference/apis/js-apis-app-ability-uiAbility.md#uiabilityonsavestate) of the [Ability](../reference/apis/js-apis-app-ability-uiAbility.md). Finally, the application is restarted.
...@@ -71,7 +54,7 @@ Common fault types include JavaScript application crash, application freezing, a ...@@ -71,7 +54,7 @@ Common fault types include JavaScript application crash, application freezing, a
| Fault | Fault Listening | State Saving| Automatic Restart| Log Query| | Fault | Fault Listening | State Saving| Automatic Restart| Log Query|
| ----------|--------- |--------- |--------- |--------- | | ----------|--------- |--------- |--------- |--------- |
| [JS_CRASH](../reference/apis/js-apis-faultLogger.md#faulttype) | Supported|Supported|Supported|Supported| | [JS_CRASH](../reference/apis/js-apis-faultLogger.md#faulttype) | Supported|Supported|Supported|Supported|
| [APP_FREEZE](../reference/apis/js-apis-faultLogger.md#faulttype) | Not supported|Supported|Supported|Supported| | [APP_FREEZE](../reference/apis/js-apis-faultLogger.md#faulttype) | Not supported|Not supported|Supported|Supported|
| [CPP_CRASH](../reference/apis/js-apis-faultLogger.md#faulttype) | Not supported|Not supported|Not supported|Supported| | [CPP_CRASH](../reference/apis/js-apis-faultLogger.md#faulttype) | Not supported|Not supported|Not supported|Supported|
**State Saving** in the table header means saving of the application state when a fault occurs. To protect user data as much as possible when an AppFreeze occurs, you can adopt either the periodic or automatic way, and the latter will save user data when an ability is switched to the background. **State Saving** in the table header means saving of the application state when a fault occurs. To protect user data as much as possible when an AppFreeze occurs, you can adopt either the periodic or automatic way, and the latter will save user data when an ability is switched to the background.
...@@ -96,31 +79,19 @@ export default class MyAbilityStage extends AbilityStage { ...@@ -96,31 +79,19 @@ export default class MyAbilityStage extends AbilityStage {
appRecovery.SaveModeFlag.SAVE_WITH_FILE); appRecovery.SaveModeFlag.SAVE_WITH_FILE);
} }
} }
```
### Enabling Application Recovery for the Specified Abilities
Generally, the ability configuration list is named **module.json5**.
```json
{
"abilities": [
{
"name": "EntryAbility",
"recoverable": true,
}]
}
``` ```
### Saving and Restoring Data ### Saving and Restoring Data
After enabling **appRecovery**, you can use this function by either actively or passively saving the application state and restoring data in the ability. After enabling **appRecovery**, you can use this function by either actively or passively saving the application state and restoring data in the ability.
The following is an example of **EntryAbility**: The following is an example of **MainAbility**:
#### Importing the Service Package #### Importing the Service Package
```ts ```ts
import errorManager from '@ohos.app.ability.errorManager'; import errorManager from '@ohos.app.ability.errorManager'
import appRecovery from '@ohos.app.ability.appRecovery'; import appRecovery from '@ohos.app.ability.appRecovery'
import AbilityConstant from '@ohos.app.ability.AbilityConstant'; import AbilityConstant from '@ohos.app.ability.AbilityConstant'
``` ```
#### Actively Saving the Application State and Restoring Data #### Actively Saving the Application State and Restoring Data
...@@ -139,7 +110,7 @@ import AbilityConstant from '@ohos.app.ability.AbilityConstant'; ...@@ -139,7 +110,7 @@ import AbilityConstant from '@ohos.app.ability.AbilityConstant';
onWindowStageCreate(windowStage) { onWindowStageCreate(windowStage) {
// Main window is created, set main page for this ability // Main window is created, set main page for this ability
console.log("[Demo] EntryAbility onWindowStageCreate") console.log("[Demo] MainAbility onWindowStageCreate")
globalThis.registerObserver = (() => { globalThis.registerObserver = (() => {
registerId = errorManager.on('error', callback); registerId = errorManager.on('error', callback);
...@@ -151,12 +122,12 @@ import AbilityConstant from '@ohos.app.ability.AbilityConstant'; ...@@ -151,12 +122,12 @@ import AbilityConstant from '@ohos.app.ability.AbilityConstant';
- Save data. - Save data.
After the callback triggers **appRecovery.saveAppState()**, **onSaveState(state, wantParams)** of **EntryAbility** is triggered. After the callback triggers **appRecovery.saveAppState()**, **onSaveState(state, wantParams)** of **MainAbility** is triggered.
```ts ```ts
onSaveState(state, wantParams) { onSaveState(state, wantParams) {
// Ability has called to save app data // Ability has called to save app data
console.log("[Demo] EntryAbility onSaveState") console.log("[Demo] MainAbility onSaveState")
wantParams["myData"] = "my1234567"; wantParams["myData"] = "my1234567";
return AbilityConstant.OnSaveResult.ALL_AGREE; return AbilityConstant.OnSaveResult.ALL_AGREE;
} }
...@@ -164,12 +135,12 @@ After the callback triggers **appRecovery.saveAppState()**, **onSaveState(state, ...@@ -164,12 +135,12 @@ After the callback triggers **appRecovery.saveAppState()**, **onSaveState(state,
- Restore data. - Restore data.
After the callback triggers **appRecovery.restartApp()**, the application is restarted. After the restart, **onCreate(want, launchParam)** of **EntryAbility** is called, and the saved data is stored in **parameters** of **want**. After the callback triggers **appRecovery.restartApp()**, the application is restarted. After the restart, **onCreate(want, launchParam)** of **MainAbility** is called, and the saved data is in **parameters** of **want**.
```ts ```ts
storage: LocalStorage storage: LocalStorage
onCreate(want, launchParam) { onCreate(want, launchParam) {
console.log("[Demo] EntryAbility onCreate") console.log("[Demo] MainAbility onCreate")
globalThis.abilityWant = want; globalThis.abilityWant = want;
if (launchParam.launchReason == AbilityConstant.LaunchReason.APP_RECOVERY) { if (launchParam.launchReason == AbilityConstant.LaunchReason.APP_RECOVERY) {
this.storage = new LocalStorage(); this.storage = new LocalStorage();
...@@ -185,7 +156,7 @@ onCreate(want, launchParam) { ...@@ -185,7 +156,7 @@ onCreate(want, launchParam) {
```ts ```ts
onWindowStageDestroy() { onWindowStageDestroy() {
// Main window is destroyed, release UI related resources // Main window is destroyed, release UI related resources
console.log("[Demo] EntryAbility onWindowStageDestroy") console.log("[Demo] MainAbility onWindowStageDestroy")
globalThis.unRegisterObserver = (() => { globalThis.unRegisterObserver = (() => {
errorManager.off('error', registerId, (err) => { errorManager.off('error', registerId, (err) => {
...@@ -200,10 +171,10 @@ onWindowStageDestroy() { ...@@ -200,10 +171,10 @@ onWindowStageDestroy() {
This is triggered by the recovery framework. You do not need to register an **ErrorObserver** callback. You only need to implement **onSaveState** for application state saving and **onCreate** for data restore. This is triggered by the recovery framework. You do not need to register an **ErrorObserver** callback. You only need to implement **onSaveState** for application state saving and **onCreate** for data restore.
```ts ```ts
export default class EntryAbility extends Ability { export default class MainAbility extends Ability {
storage: LocalStorage storage: LocalStorage
onCreate(want, launchParam) { onCreate(want, launchParam) {
console.log("[Demo] EntryAbility onCreate") console.log("[Demo] MainAbility onCreate")
globalThis.abilityWant = want; globalThis.abilityWant = want;
if (launchParam.launchReason == AbilityConstant.LaunchReason.APP_RECOVERY) { if (launchParam.launchReason == AbilityConstant.LaunchReason.APP_RECOVERY) {
this.storage = new LocalStorage(); this.storage = new LocalStorage();
...@@ -215,26 +186,9 @@ export default class EntryAbility extends Ability { ...@@ -215,26 +186,9 @@ export default class EntryAbility extends Ability {
onSaveState(state, wantParams) { onSaveState(state, wantParams) {
// Ability has called to save app data // Ability has called to save app data
console.log("[Demo] EntryAbility onSaveState") console.log("[Demo] MainAbility onSaveState")
wantParams["myData"] = "my1234567"; wantParams["myData"] = "my1234567";
return AbilityConstant.OnSaveResult.ALL_AGREE; return AbilityConstant.OnSaveResult.ALL_AGREE;
} }
} }
``` ```
#### Restart Flag for the Failed Ability
If the failed ability is restarted again, the [ABILITY_RECOVERY_RESTART](../reference/apis/js-apis-app-ability-wantConstant.md#wantconstantparams) flag will be added as a **parameters** member for the **want** parameter in **onCreate** and its value is **true**.
```ts
import UIAbility from '@ohos.app.ability.UIAbility';
import wantConstant from '@ohos.app.ability.wantConstant';
export default class EntryAbility extends UIAbility {
onCreate(want, launchParam) {
if (want.parameters[wantConstant.Params.ABILITY_RECOVERY_RESTART] != undefined &&
want.parameters[wantConstant.Params.ABILITY_RECOVERY_RESTART] == true) {
console.log("This ability need to recovery");
}
}
}
```
# cppcrash Log Analysis
## Introduction
A process crash refers to a C/C++ runtime crash. The FaultLogger module of OpenHarmony provides capabilities such as process crash detection, log collection, log storage, and log reporting, helping you to locate faults more effectively.
In this document, you'll be guided through how to implement process crash detection, crash log collection, and crash log analysis. Before getting started, make sure you have basic knowledge about C/C++ program stacks.
## Process Crash Detection
Process crash detection is implemented based on the Linux signal mechanism. Currently, C/C++ crash exception signals listed in the following table are supported.
| Signal Value| Signal| Description| Trigger Cause|
| ------ | --------- | --------------- | ------------------------------------------- |
| 4 | SIGILL | Invalid instruction | An invalid, incorrectly formatted, unknown, or privileged instruction is executed.|
| 5 | SIGTRAP | Breakpoint or trap | An exception occurs or a trap instruction is executed.|
| 6 | SIGABRT | Process abort | The process is aborted abnormally. Generally, this problem occurs if the process calls the `abort()` function of the standard function library.|
| 7 | SIGBUS | Illegal memory access | The process accesses an aligned or nonexistent physical address.|
| 8 | SIGFPE | Floating-point exception | The process performs an incorrect arithmetic operation, for example, a 0 divisor, floating point overflow, or integer overflow.|
| 11 | SIGSEGV | Invalid memory access | The process accesses an invalid memory reference.|
| 16 | SIGSTKFLT | Stack error | The processor performs an incorrect stack operation, such as a pop when the stack is empty or a push when the stack is full.|
| 31 | SIGSYS | Incorrect system call | An incorrect or invalid parameter is used in a system call.|
## Crash Log Collection
Process crash log is the fault log managed together with the app freeze and JS application crash logs by the FaultLogger module. You can collect process crash logs in any of the following ways:
### Collecting Logs by Using Shell
- Fault logs in the `/data/log/faultlog/faultlogger/` directory of the device. The log files are named in the format of `cppcrash-process name-process UID-time (seconds level)`. They contain only information such as the device name, system version, and process crash call stack.
![cppcrash-faultlogger-log](figures/20230407112159.png)
- Fault logs in the `/data/log/faultlog/temp/` directory of the device. The log files are named in the format of `cppcrash-process name-process PID-system timestamp (seconds level)`. In addition to basic information, they also contain information such as the stack memory and process maps at the time of process crash.
![cppcrash-temp-log](figures/20230407111853.png)
### Collecting Logs by Using DevEco Studio
DevEco Studio collects process crash logs from `/data/log/faultlog/faultlogger/` to FaultLog, where logs are displayed by process name, fault, and time.
![DevEco Studio cppcrash](figures/20230407112620.png)
### Collecting Logs by Using faultLogger APIs
The FaultLogger module provides APIs to query various fault information. For details, see [@ohos.faultLogger](../reference/apis/js-apis-faultLogger.md).
## Process Crash Log Analysis
### Log Format
The following is an example process crash log archived by DevEco Studio in FaultLog:
```
Generated by HiviewDFX@OpenHarmony
==================================================================
Device info:OpenHarmony 3.2 <- Device information
Build info:OpenHarmony 4.0.5.5 <- Version information
Module name:crasher_c <- Module name
Pid:1205 <- Process ID
Uid:0 <- User ID
Reason:Signal:SIGSEGV(SEGV_ACCERR)@0x0042d33d <- Exception information
Thread name:crasher <- Abnormal thread
#00 pc 0000332c /data/crasher(TriggerSegmentFaultException+15)(8bc37ceb8d6169e919d178fdc7f5449e) <- Call stack
#01 pc 000035c7 /data/crasher(ParseAndDoCrash+277)(8bc37ceb8d6169e919d178fdc7f5449e)
#02 pc 00003689 /data/crasher(main+39)(8bc37ceb8d6169e919d178fdc7f5449e)
#03 pc 000c3b08 /system/lib/ld-musl-arm.so.1(__libc_start_main+116)
#04 pc 000032f8 /data/crasher(_start_c+112)(8bc37ceb8d6169e919d178fdc7f5449e)
#05 pc 00003284 /data/crasher(_start+32)(8bc37ceb8d6169e919d178fdc7f5449e)
...
```
### Locating Faults Through Logs
1. Determine the faulty module and fault type based on fault logs.
Generally, you can identify the faulty module based on the crash process name and identify the crash cause based on the signal. Besides, you can restore the function call chain of the crash stack based on the method name in the stack.
In the example, **SIGSEGV** is thrown by the Linux kernel because of access to an invalid memory address. The problem occurs in the **TriggerSegmentFaultException** function.
In most scenarios, a crash is caused by the top layer of the crash stack, such as null pointer access and proactive program abort.
If the cause cannot be located through the call stack, you need to check for other faults, for example, memory corruption or stack overflow.
2. Use the addr2line tool of Linux to parse the code line number to restore the call stack at the time of process crash.
When using the addr2line tool to parse the code line number of the crash stack, make sure that binary files with debugging information is used. Generally, such files are generated during version build or application build.
Application binary files are located in DevEco Studio's temporary directory for application build, for example, `build/default/intermediates/libs`.
System binary files are stored in the directories listed below. For versions that are directly obtained, the binary files are archived in the image package.
```
\code root directory\out\product\lib.unstripped
\code root directory\out\product\exe.unstripped
```
You can run `apt-get install addr2line` to install the addr2line tool on Linux.
On On DevEco Studio, you can also use the llvm-addr2line tool archived in the SDK to parse code line numbers. The usage method is the same.
The following example shows how to use the addr2line tool to parse the code line number based on the offset address:
```
root:~/OpenHarmony/out/rk3568/exe.unstripped/hiviewdfx/faultloggerd$ addr2line -e crasher 0000332c
base/hiviewdfx/faultloggerd/tools/crasher/dfx_crasher.c:57
```
In this example, the crash is caused by assignment of a value to an unwritable area. It is in code line 57 in the **dfx_crasher.c** file. You can modify it to avoid the crash.
If the obtained code line number is seemingly incorrect, you can fine-tune the address (for example, subtract the address by 1) or disable some compilation optimization items. It is known that the obtained code line number may be incorrect when Link Time Optimization (LTO) is enabled.
...@@ -23,8 +23,7 @@ When an asynchronous callback is used, the return value can be processed directl ...@@ -23,8 +23,7 @@ When an asynchronous callback is used, the return value can be processed directl
| API | Description | | API | Description |
| ------------------------------ | ------------------------------------------------------------ | | ------------------------------ | ------------------------------------------------------------ |
| onUnhandledException(errMsg: string): void | Called when an uncaught exception is reported after the application is registered.| | onUnhandledException(errMsg: string): void | Called when an application generates an uncaught exception after being registered.|
| onException?(errObject: Error): void | Called when an application exception is reported to the JavaScript layer after the application is registered.|
### Result Codes for Unregistering an Observer ### Result Codes for Unregistering an Observer
...@@ -44,13 +43,6 @@ let registerId = -1; ...@@ -44,13 +43,6 @@ let registerId = -1;
let callback = { let callback = {
onUnhandledException: function (errMsg) { onUnhandledException: function (errMsg) {
console.log(errMsg); console.log(errMsg);
},
onException: function (errorObj) {
console.log('onException, name: ', errorObj.name);
console.log('onException, message: ', errorObj.message);
if (typeof(errorObj.stack) === 'string') {
console.log('onException, stack: ', errorObj.stack);
}
} }
} }
......
...@@ -49,11 +49,11 @@ The following example illustrates how to log and subscribe to button click event ...@@ -49,11 +49,11 @@ The following example illustrates how to log and subscribe to button click event
```js ```js
import hilog from '@ohos.hilog'; import hilog from '@ohos.hilog';
import UIAbility from '@ohos.app.ability.UIAbility'; import Ability from '@ohos.application.Ability'
import Window from '@ohos.window' import Window from '@ohos.window'
import hiAppEvent from '@ohos.hiviewdfx.hiAppEvent' import hiAppEvent from '@ohos.hiviewdfx.hiAppEvent'
export default class EntryAbility extends UIAbility { export default class EntryAbility extends Ability {
onCreate(want, launchParam) { onCreate(want, launchParam) {
hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO); hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO);
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate'); hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
......
# HiLog Development # HiLog Development (Native)
## Overview ## Introduction
HiLog is the log system of OpenHarmony that provides logging for the system framework, services, and applications to record information on user operations and system running status. HiLog is the log system of OpenHarmony that provides logging for the system framework, services, and applications to record information on user operations and system running status.
> **NOTE** > **NOTE**
> >
> This development guide is applicable only when you use Native APIs for application development. For details about the APIs, see [HiLog Native API Reference](https://gitee.com/openharmony-sig/interface_native_header/blob/master/en/native_sdk/dfx/log.h). > This development guide is applicable only when you use Native APIs for application development. For details about the APIs, see [HiLog Native API Reference](../reference/native-apis/_hi_log.md).
## Available APIs ## Available APIs
| API/Macro| Description| | API/Macro| Description|
| -------- | -------- | | -------- | -------- |
| int OH_LOG_Print(LogType type, LogLevel level, unsigned int domain, const char *tag, const char *fmt, ...) | Outputs logs based on the specified log type, log level, service domain, log tag, and variable parameters determined by the format specifier and privacy identifier in the printf format.<br>Input parameters: See [Parameter Description](#parameter-description).<br>Output parameters: None<br>Return value: total number of bytes if log printing is successful; **-1** otherwise.| | int OH_LOG_Print(LogType type, LogLevel level, unsigned int domain, const char *tag, const char *fmt, ...) | Outputs logs based on the specified log type, log level, service domain, log tag, and variable parameters determined by the format specifier and privacy identifier in the printf format.<br>Input arguments: See [Parameter Description](#parameter-description).<br>Output arguments: None<br>Return value: total number of bytes if log printing is successful; **-1** otherwise.|
| #define OH_LOG_DEBUG(type, ...) ((void)OH_LOG_Print((type), LOG_DEBUG, LOG_DOMAIN, LOG_TAG, \_*VA*ARGS__))| Outputs DEBUG logs. This is a function-like macro.| | #define OH_LOG_DEBUG(type, ...) ((void)OH_LOG_Print((type), LOG_DEBUG, LOG_DOMAIN, LOG_TAG, \_*VA*ARGS__))| Outputs DEBUG logs. This is a function-like macro.|
| #define OH_LOG_INFO(type, ...) ((void)OH_LOG_Print((type), LOG_INFO, LOG_DOMAIN, LOG_TAG, \_*VA*ARGS__)) | Outputs INFO logs. This is a function-like macro.| | #define OH_LOG_INFO(type, ...) ((void)OH_LOG_Print((type), LOG_INFO, LOG_DOMAIN, LOG_TAG, \_*VA*ARGS__)) | Outputs INFO logs. This is a function-like macro.|
| #define OH_LOG_WARN(type, ...) ((void)OH_LOG_Print((type), LOG_WARN, LOG_DOMAIN, LOG_TAG, \_*VA*ARGS__)) | Outputs WARN logs. This is a function-like macro.| | #define OH_LOG_WARN(type, ...) ((void)OH_LOG_Print((type), LOG_WARN, LOG_DOMAIN, LOG_TAG, \_*VA*ARGS__)) | Outputs WARN logs. This is a function-like macro.|
| #define OH_LOG_ERROR(type, ...) ((void)OH_LOG_Print((type), LOG_ERROR, LOG_DOMAIN, LOG_TAG, \_*VA*ARGS__)) | Outputs ERROR logs. This is a function-like macro.| | #define OH_LOG_ERROR(type, ...) ((void)OH_LOG_Print((type), LOG_ERROR, LOG_DOMAIN, LOG_TAG, \_*VA*ARGS__)) | Outputs ERROR logs. This is a function-like macro.|
| #define OH_LOG_FATAL(type, ...) ((void)OH_LOG_Print((type), LOG_FATAL, LOG_DOMAIN, LOG_TAG, \_*VA*ARGS__)) | Outputs FATAL logs. This is a function-like macro.| | #define OH_LOG_FATAL(type, ...) ((void)OH_LOG_Print((type), LOG_FATAL, LOG_DOMAIN, LOG_TAG, \_*VA*ARGS__)) | Outputs FATAL logs. This is a function-like macro.|
| bool OH_LOG_IsLoggable(unsigned int domain, const char *tag, LogLevel level) | Checks whether logs of the specified service domain, tag, and level can be printed.<br>Input parameters: See [Parameter Description](#parameter-description).<br>Output arguments: none<br>Return value: **true** if the specified logs can be printed; **false** otherwise.| | bool OH_LOG_IsLoggable(unsigned int domain, const char *tag, LogLevel level) | Checks whether logs of the specified service domain, tag, and level can be printed.<br>Input arguments: See [Parameter Description](#parameter-description).<br>Output arguments: none<br>Return value: **true** if the specified logs can be printed; **false** otherwise.|
## Parameter Description ## Parameter Description
| Name| Type | Mandatory| Description | | Name| Type | Mandatory| Description |
| ------ | ------ | ---- | ------------------------------------------------------------ | | ------ | ------ | ---- | ------------------------------------------------------------ |
| type | enum | Yes | Enum of log printing types. The default value is **LOG_APP** for application logs.| | type | enum | Yes | Log printing type. The default value is **LOG_APP** for application logs.|
| level | enum | Yes | Log printing level. For details, see [Log Level](#loglevel).| | level | enum | Yes | Log printing level. For details, see [Log Level](#loglevel).|
| domain | number | Yes | Service domain of logs. The value ranges from **0x0** to **0xFFFF**.<br>You can define the value as required. | | domain | number | Yes | Service domain of logs. The value ranges from **0x0** to **0xFFFF**.<br>You can define the value as required. |
| tag | string | Yes | Log tag in the string format. You are advised to use this parameter to identify a particular service behavior or the class holding the ongoing method.| | tag | string | Yes | Log tag in the string format. You are advised to use this parameter to identify a particular service behavior or the class holding the ongoing method.|
...@@ -43,7 +43,7 @@ Log level. ...@@ -43,7 +43,7 @@ Log level.
| ERROR | 6 | Log level used to record program or functional errors that affect the normal running or use of the functionality and can be fixed at a high cost, for example, by resetting data.| | ERROR | 6 | Log level used to record program or functional errors that affect the normal running or use of the functionality and can be fixed at a high cost, for example, by resetting data.|
| FATAL | 7 | Log level used to record program or functionality crashes that cannot be rectified. | FATAL | 7 | Log level used to record program or functionality crashes that cannot be rectified.
## Development Examples ## Development Example
1. Add the link of **libhilog_ndk.z.so** to **CMakeLists.txt**: 1. Add the link of **libhilog_ndk.z.so** to **CMakeLists.txt**:
``` ```
......
...@@ -2,7 +2,9 @@ ...@@ -2,7 +2,9 @@
## Introduction ## Introduction
hiTraceChain is a lightweight implementation of the cloud-based distributed call chain tracing. It allows applications to trace cross-thread, cross-process, and cross-device service calls. The hiTraceChain module generates a unique **chainId** for a service process and passes it to various information (including application events, system time, and logs) specific to the service process. During debugging and fault locating, you can use the unique **chainId** to quickly correlate various information related to the service process. The hiTraceChain module provides APIs to implement call chain tracing throughout a service process. This can help you quickly obtain the run log for the call chain of a specified service process and locate faults in inter-device, inter-process, or inter-thread communications. The hiTraceChain module provides APIs to implement call chain tracing throughout a service process. This can help you quickly obtain the run log for the call chain of a specified service process and locate faults in inter-device, inter-process, or inter-thread communications.
hiTraceChain is a lightweight implementation of the cloud-based distributed call chain tracing. It allows applications to trace cross-thread, cross-process, and cross-device service calls. The hiTraceChain module generates a unique **chainId** for a service process and passes it to various information (including application events, system time, and logs) specific to the service process. During debugging and fault locating, you can use the unique **chainId** to quickly correlate various information related to the service process.
## Basic Concepts ## Basic Concepts
...@@ -16,106 +18,47 @@ The APIs for distributed call chain tracing are provided by the **hiTraceChain** ...@@ -16,106 +18,47 @@ The APIs for distributed call chain tracing are provided by the **hiTraceChain**
**APIs for distributed call chain tracing** **APIs for distributed call chain tracing**
| API | Return Value | Description | | API| Return Value| Description|
| ------------------------------------------------------------------------------------------------------------------- | -------------- | ------------ | | ------------------------------------------------------------------------------------------------------------------- | -------------- | ------------ |
| hiTraceChain.begin(name: string, flags: number = HiTraceFlag.DEFAULT) | HiTraceId | Starts call chain tracing. | | hiTraceChain.begin(name: string, flags: number = HiTraceFlag.DEFAULT) | HiTraceId | Starts call chain tracing.|
| hiTraceChain.end(id: HiTraceId) | void | Stops call chain tracing. | | hiTraceChain.tracepoint(mode: HiTraceCommunicationMode, type: HiTraceTracepointType, id: HiTraceId, msg?: string) | void | Creates a trace point.|
| hiTraceChain.end(id: HiTraceId) | void | Stops call chain tracing.|
## How to Develop ## How to Develop
The following example illustrates how to simulate one-time [system event logging](../reference/apis/js-apis-hisysevent.md) to implement cross-thread distributed call chain tracing in a single HAP service. In this example, distributed call chain tracing begins when the application startup execution page is loaded and stops when the service usage is completed.
1. Create an eTS application project. In the displayed **Project** window, choose **entry** > **src** > **main** > **ets** > **pages** > **index.ets**, and double-click **index.ets**. Then, add a button to trigger system event logging. 1. Create a JS application project. In the displayed **Project** window, choose **entry** > **src** > **main** > **js** > **default** > **pages** > **index**, and double-click **index.js**. Add the code to implement call chain tracing upon page loading. The sample code is as follows:
```ts
import hiTraceChain from '@ohos.hiTraceChain';
import hiSysEvent from '@ohos.hiSysEvent';
@Entry
@Component
struct Index {
@State message: string = 'Start writing system event';
build() {
Row() {
Column() {
Button(this.message)
.fontSize(20)
.margin(5)
.width(350)
.height(60)
.fontWeight(FontWeight.Bold)
.onClick(() => {
try {
// Enable distributed call chain tracing before the service starts.
let traceId = hiTraceChain.begin("Write a new system event", hiTraceChain.HiTraceFlag.INCLUDE_ASYNC);
// Implement one-time system event logging when the service starts.
hiSysEvent.write({
domain: "RELIABILITY",
name: "STACK",
eventType: hiSysEvent.EventType.FAULT,
params: {
PID: 1,
UID: 1,
PACKAGE_NAME: "com.demo.hitracechain",
PROCESS_NAME: "hitracechaindemo",
MSG: "no msg."
}
}).then((val) => {
console.info(`write result is ${val}`);
// Disable distributed call chain tracing when the service ends.
hiTraceChain.end(traceId);
}).catch((err) => {
console.error(`error message is ${err.message}`);
});
} catch (err) {
console.error(`error message is ${err.message}`);
}
})
}
.width('100%')
}
.height('100%')
}
}
```
2. Touch the run button on the IDE to run the project. Then, touch the **Start writing system event** button on the application UI to trigger system event logging.
3. View the information printed in the **Log** window. You can use **.*: \[([0-9a-zA-Z]{15}),.*].*** to access distributed call chain tracing information specific to the HAP service. The process ID of the HAP service is **8801**. Two threads, whose IDs are **8801** and **8819**, are involved in the system event logging. Based on the chain ID **edcfa53017a88e3**, you can then effectively trace the log information of the two threads.
```text
07-05 19:50:47.690 8801-8801/com.demo.hitracechain I C02d03/HiTraceC: [edcfa53017a88e3, 0, 0] HiTraceBegin name:Write a new system event flags:0x01.
07-05 19:50:47.690 8801-8801/com.demo.hitracechain D C02d03/HITRACE_UTIL_NAPI: [edcfa53017a88e3, 0, 0] Native2Js: chainId is edcfa53017a88e3.
07-05 19:50:47.690 8801-8801/com.demo.hitracechain D C02d03/HITRACE_UTIL_NAPI: [edcfa53017a88e3, 0, 0] Native2Js: spanId is 0.
07-05 19:50:47.690 8801-8801/com.demo.hitracechain D C02d03/HITRACE_UTIL_NAPI: [edcfa53017a88e3, 0, 0] Native2Js: parentSpanId is 0.
07-05 19:50:47.690 8801-8801/com.demo.hitracechain D C02d03/HITRACE_UTIL_NAPI: [edcfa53017a88e3, 0, 0] Native2Js: flags is 1.
07-05 19:50:47.690 8801-8801/com.demo.hitracechain D C02d08/NAPI_HISYSEVENT_UTIL: [edcfa53017a88e3, 0, 0] domain is RELIABILITY.
07-05 19:50:47.690 8801-8801/com.demo.hitracechain D C02d08/NAPI_HISYSEVENT_UTIL: [edcfa53017a88e3, 0, 0] name is STACK.
07-05 19:50:47.690 8801-8801/com.demo.hitracechain D C02d08/NAPI_HISYSEVENT_UTIL: [edcfa53017a88e3, 0, 0] eventType is 1.
07-05 19:50:47.690 8801-8801/com.demo.hitracechain E C02d08/NAPI_HISYSEVENT_UTIL: [edcfa53017a88e3, 0, 0] napi value type not match: valueType=3, typeName=6.
07-05 19:50:47.690 8801-8801/com.demo.hitracechain E C02d08/NAPI_HISYSEVENT_UTIL: [edcfa53017a88e3, 0, 0] napi value type not match: valueType=3, typeName=6.
07-05 19:50:47.690 8801-8801/com.demo.hitracechain E C02d08/NAPI_HISYSEVENT_UTIL: [edcfa53017a88e3, 0, 0] napi value type not match: valueType=4, typeName=6.
07-05 19:50:47.690 8801-8801/com.demo.hitracechain E C02d08/NAPI_HISYSEVENT_UTIL: [edcfa53017a88e3, 0, 0] napi value type not match: valueType=4, typeName=6.
07-05 19:50:47.690 8801-8801/com.demo.hitracechain E C02d08/NAPI_HISYSEVENT_UTIL: [edcfa53017a88e3, 0, 0] napi value type not match: valueType=4, typeName=6.
07-05 19:50:47.690 8801-8801/com.demo.hitracechain D C02d08/NAPI_HISYSEVENT_UTIL: [edcfa53017a88e3, 0, 0] create napi value of string type, value is JSHiSysEventWrite.
07-05 19:50:47.690 8801-8801/com.demo.hitracechain I C03900/Ace: [edcfa53017a88e3, 0, 0] [flutter_ace_view.cpp(operator())-(0)] Mark 0 id Touch Event Processed
07-05 19:50:47.690 8801-8801/com.demo.hitracechain D C02800/ClientMsgHandler: [edcfa53017a88e3, 0, 0] in OnDispatchEventProcessed, enter
07-05 19:50:47.690 8801-8801/com.demo.hitracechain D C02800/ANRHandler: [edcfa53017a88e3, 0, 0] in SetLastProcessedEventId, enter
07-05 19:50:47.690 8801-8819/com.demo.hitracechain D C02d08/HISYSEVENT: [edcfa53017a88e3, 0, 0] size=312, sysevent={"domain_":"RELIABILITY","name_":"STACK","type_":1,"time_":47591447690,"tz_":"+0000","pid_":8801,"tid_":8819,"uid_":20010045,"traceid_":"edcfa53017a88e3","spanid_":"0","pspanid_":"0","trace_flag_":1,"UID":1,"PID":1,"MSG":"no msg.","PROCESS_NAME":"hitracechaindemo","PACKAGE_NAME":"com.demo.hitracechain"}
07-05 19:50:47.690 8801-8801/com.demo.hitracechain D C02800/ANRHandler: [edcfa53017a88e3, 0, 0] in SetLastProcessedEventId, Processed event type:0, id:831, actionTime:6694499314, currentTime:6694501330, timeoutTime:4997984
07-05 19:50:47.691 8801-8801/com.demo.hitracechain D C02800/ANRHandler: [edcfa53017a88e3, 0, 0] in SetLastProcessedEventId, leave
07-05 19:50:47.691 8801-8801/com.demo.hitracechain D C02800/ClientMsgHandler: [edcfa53017a88e3, 0, 0] in OnDispatchEventProcessed, leave
07-05 19:50:47.691 8801-8819/com.demo.hitracechain D C02d08/HISYSEVENT: [edcfa53017a88e3, 0, 0] reset send buffer size old=245760, new=524288
07-05 19:50:47.691 8801-8819/com.demo.hitracechain D C02d08/HISYSEVENT: [edcfa53017a88e3, 0, 0] HiSysEvent send data successful
07-05 19:50:47.691 8801-8801/com.demo.hitracechain D C02d08/NAPI_HISYSEVENT_UTIL: [edcfa53017a88e3, 0, 0] create napi value of int32 type, value is 0.
07-05 19:50:47.691 8801-8801/com.demo.hitracechain E A0fefe/JsApp: [edcfa53017a88e3, 399db38, 0] write result is 0
07-05 19:50:47.691 8801-8801/com.demo.hitracechain D C02d03/HITRACE_UTIL_NAPI: [edcfa53017a88e3, 399db38, 0] Js2Native: chainId is edcfa53017a88e3.
07-05 19:50:47.691 8801-8801/com.demo.hitracechain D C02d03/HITRACE_UTIL_NAPI: [edcfa53017a88e3, 399db38, 0] Js2Native: spanId is 0.
07-05 19:50:47.691 8801-8801/com.demo.hitracechain D C02d03/HITRACE_UTIL_NAPI: [edcfa53017a88e3, 399db38, 0] Js2Native: parentSpanId is 0.
07-05 19:50:47.691 8801-8801/com.demo.hitracechain D C02d03/HITRACE_UTIL_NAPI: [edcfa53017a88e3, 399db38, 0] Js2Native: flags is 1.
07-05 19:50:47.691 8801-8801/com.demo.hitracechain I C02d03/HiTraceC: [edcfa53017a88e3, 399db38, 0] HiTraceEnd.
``` ```
import hiTraceChain from '@ohos.hiTraceChain'
## About Cross-Process/Cross-Device Distributed Call Chain Tracing export default {
data: {
title: ""
},
onInit() {
this.title = this.$t('strings.world');
// 1. Enable distributed call chain tracing.
let asyncTraceId = hiTraceChain.begin("business", hiTraceChain.HiTraceFlag.INCLUDE_ASYNC | hiTraceChain.HiTraceFlag.DONOT_CREATE_SPAN);
// 2. Start the service process.
console.log(`business start`);
// 3. Add a trace point.
hiTraceChain.tracepoint(hiTraceChain.HiTraceCommunicationMode.THREAD, hiTraceChain.HiTraceTracepointType.SS, asyncTraceId, "Just an example");
// 4. Keep the service process running.
console.log(`business running`);
// 5. End the service process.
console.log(`business end`);
// 6. Stop call chain tracing.
hiTraceChain.end(asyncTraceId);
}
}
```
Cross-process/cross-device distributed call chain tracing depends on the NAPI implementation of the corresponding service APIs of each OpenHarmony module. For details, see the [HiTraceChain Development](../../device-dev/subsystems/subsys-dfx-hitracechain.md). 2. Click the run button on the application page. Then, you'll obtain the log information for service analysis.
...@@ -17,7 +17,7 @@ hiTraceMeter provides APIs for system performance tracing. You can call the APIs ...@@ -17,7 +17,7 @@ hiTraceMeter provides APIs for system performance tracing. You can call the APIs
## Constraints ## Constraints
- Due to the asynchronous I/O feature of JS, the hiTraceMeter module provides only asynchronous APIs. Due to the asynchronous I/O feature of JS, the hiTraceMeter module provides only asynchronous APIs.
## Available APIs ## Available APIs
......
...@@ -937,102 +937,102 @@ Indicates that the domain account status has changed. ...@@ -937,102 +937,102 @@ Indicates that the domain account status has changed.
- Value: **usual.event.DOMAIN_ACCOUNT_STATUS_CHANGED** - Value: **usual.event.DOMAIN_ACCOUNT_STATUS_CHANGED**
- Required subscriber permissions: none - Required subscriber permissions: none
## COMMON_EVENT_SIM_STATE_CHANGED<sup>10+<sup> ## [COMMON_EVENT_SIM_STATE_CHANGED<sup>10+<sup>](./common_event/commonEvent-telephony.md)
Indicates that the SIM card state has changed. Indicates that the SIM card state has changed.
- Value: **usual.event.SIM_STATE_CHANGED** - Value: **usual.event.SIM_STATE_CHANGED**
- Required subscriber permissions: none - Required subscriber permissions: none
## COMMON_EVENT_SMS_RECEIVED_COMPLETED<sup>10+<sup> ## [COMMON_EVENT_SMS_RECEIVED_COMPLETED<sup>10+<sup>](./common_event/commonEvent-telephony.md)
Indicates that the SMS message is received. Indicates that the SMS message is received.
- Value: **usual.event.SMS_RECEIVED_COMPLETED** - Value: **usual.event.SMS_RECEIVED_COMPLETED**
- Required subscriber permissions: ohos.permission.RECEIVE_SMS - Required subscriber permissions: ohos.permission.RECEIVE_SMS
## COMMON_EVENT_SMS_EMERGENCY_CB_RECEIVE_COMPLETED<sup>10+<sup> ## [COMMON_EVENT_SMS_EMERGENCY_CB_RECEIVE_COMPLETED<sup>10+<sup>](./common_event/commonEvent-telephony.md)
Indicates that an emergency cell broadcast message is received. Indicates that an emergency cell broadcast message is received.
- Value: **usual.event.SMS_EMERGENCY_CB_RECEIVE_COMPLETED** - Value: **usual.event.SMS_EMERGENCY_CB_RECEIVE_COMPLETED**
- Required subscriber permissions: ohos.permission.RECEIVE_SMS - Required subscriber permissions: ohos.permission.RECEIVE_SMS
## COMMON_EVENT_SMS_CB_RECEIVE_COMPLETED<sup>10+<sup> ## [COMMON_EVENT_SMS_CB_RECEIVE_COMPLETED<sup>10+<sup>](./common_event/commonEvent-telephony.md)
Indicates that a cell broadcast message is received. Indicates that a cell broadcast message is received.
- Value: **usual.event.SMS_CB_RECEIVE_COMPLETED** - Value: **usual.event.SMS_CB_RECEIVE_COMPLETED**
- Required subscriber permissions: ohos.permission.RECEIVE_SMS - Required subscriber permissions: ohos.permission.RECEIVE_SMS
## COMMON_EVENT_STK_COMMAND<sup>10+<sup> ## [COMMON_EVENT_STK_COMMAND<sup>10+<sup>](./common_event/commonEvent-telephony.md)
(Reserved, not supported yet) Indicates the STK command. (Reserved, not supported yet) Indicates the STK command.
- Value: **usual.event.STK_COMMAND** - Value: **usual.event.STK_COMMAND**
- Required subscriber permissions: none - Required subscriber permissions: none
## COMMON_EVENT_STK_SESSION_END<sup>10+<sup> ## [COMMON_EVENT_STK_SESSION_END<sup>10+<sup>](./common_event/commonEvent-telephony.md)
(Reserved, not supported yet) Indicates that an STK session ends. (Reserved, not supported yet) Indicates that an STK session ends.
- Value: **usual.event.STK_SESSION_END** - Value: **usual.event.STK_SESSION_END**
- Required subscriber permissions: none - Required subscriber permissions: none
## COMMON_EVENT_STK_CARD_STATE_CHANGED<sup>10+<sup> ## [COMMON_EVENT_STK_CARD_STATE_CHANGED<sup>10+<sup>](./common_event/commonEvent-telephony.md)
(Reserved, not supported yet) Indicates that the STK card state has changed. (Reserved, not supported yet) Indicates that the STK card state has changed.
- Value: **usual.event.STK_CARD_STATE_CHANGED** - Value: **usual.event.STK_CARD_STATE_CHANGED**
- Required subscriber permissions: ohos.permission - Required subscriber permissions: ohos.permission
## COMMON_EVENT_STK_ALPHA_IDENTIFIER<sup>10+<sup> ## [COMMON_EVENT_STK_ALPHA_IDENTIFIER<sup>10+<sup>](./common_event/commonEvent-telephony.md)
(Reserved, not supported yet) Indicates the STK alpha indicator. (Reserved, not supported yet) Indicates the STK alpha indicator.
- Value: **usual.event.STK_ALPHA_IDENTIFIER** - Value: **usual.event.STK_ALPHA_IDENTIFIER**
- Required subscriber permissions: none - Required subscriber permissions: none
## COMMON_EVENT_SMS_WAPPUSH_RECEIVE_COMPLETED<sup>10+<sup> ## [COMMON_EVENT_SMS_WAPPUSH_RECEIVE_COMPLETED<sup>10+<sup>](./common_event/commonEvent-telephony.md)
Indicates that a WAP push message is received. Indicates that a WAP push message is received.
- Value: **usual.event.SMS_WAPPUSH_RECEIVE_COMPLETED** - Value: **usual.event.SMS_WAPPUSH_RECEIVE_COMPLETED**
- Required subscriber permissions: ohos.permission.RECEIVE_SMS - Required subscriber permissions: ohos.permission.RECEIVE_SMS
## COMMON_EVENT_OPERATOR_CONFIG_CHANGED<sup>10+<sup> ## [COMMON_EVENT_OPERATOR_CONFIG_CHANGED<sup>10+<sup>](./common_event/commonEvent-telephony.md)
Indicates that the carrier configuration has been updated. Indicates that the carrier configuration has been updated.
- Value: **usual.event.OPERATOR_CONFIG_CHANGED** - Value: **usual.event.OPERATOR_CONFIG_CHANGED**
- Required subscriber permissions: none - Required subscriber permissions: none
## COMMON_EVENT_SIM_CARD_DEFAULT_SMS_SUBSCRIPTION_CHANGED<sup>10+<sup> ## [COMMON_EVENT_SIM_CARD_DEFAULT_SMS_SUBSCRIPTION_CHANGED<sup>10+<sup>](./common_event/commonEvent-telephony.md)
Indicates that the default SIM card for the SMS service has changed. Indicates that the default SIM card for the SMS service has changed.
- Value: **usual.event.DEFAULT_SMS_SUBSCRIPTION_CHANGED** - Value: **usual.event.DEFAULT_SMS_SUBSCRIPTION_CHANGED**
- Required subscriber permissions: none - Required subscriber permissions: none
## COMMON_EVENT_SIM_CARD_DEFAULT_DATA_SUBSCRIPTION_CHANGED<sup>10+<sup> ## [COMMON_EVENT_SIM_CARD_DEFAULT_DATA_SUBSCRIPTION_CHANGED<sup>10+<sup>](./common_event/commonEvent-telephony.md)
Indicates that the default SIM card for the mobile data service has changed. Indicates that the default SIM card for the mobile data service has changed.
- Value: **usual.event.DEFAULT_DATA_SUBSCRIPTION_CHANGED** - Value: **usual.event.DEFAULT_DATA_SUBSCRIPTION_CHANGED**
- Required subscriber permissions: none - Required subscriber permissions: none
## COMMON_EVENT_SIM_CARD_DEFAULT_MAIN_SUBSCRIPTION_CHANGED<sup>10+<sup> ## [COMMON_EVENT_SIM_CARD_DEFAULT_MAIN_SUBSCRIPTION_CHANGED<sup>10+<sup>](./common_event/commonEvent-telephony.md)
Indicates that the default primary SIM card has changed. Indicates that the default primary SIM card has changed.
- Value: **usual.event.SIM.DEFAULT_MAIN_SUBSCRIPTION_CHANGED** - Value: **usual.event.SIM.DEFAULT_MAIN_SUBSCRIPTION_CHANGED**
- Required subscriber permissions: none - Required subscriber permissions: none
## COMMON_EVENT_SIM_CARD_DEFAULT_VOICE_SUBSCRIPTION_CHANGED<sup>10+<sup> ## [COMMON_EVENT_SIM_CARD_DEFAULT_VOICE_SUBSCRIPTION_CHANGED<sup>10+<sup>](./common_event/commonEvent-telephony.md)
Indicates that the default SIM card for the voice service has changed. Indicates that the default SIM card for the voice service has changed.
- Value: **usual.event.DEFAULT_VOICE_SUBSCRIPTION_CHANGED** - Value: **usual.event.DEFAULT_VOICE_SUBSCRIPTION_CHANGED**
- Required subscriber permissions: none - Required subscriber permissions: none
## COMMON_EVENT_CALL_STATE_CHANGED<sup>10+<sup> ## [COMMON_EVENT_CALL_STATE_CHANGED<sup>10+<sup>](./common_event/commonEvent-telephony.md)
Indicates that the call state has changed. Indicates that the call state has changed.
- Value: **usual.event.CALL_STATE_CHANGED** - Value: **usual.event.CALL_STATE_CHANGED**
- Required subscriber permissions: ohos.permission.GET_TELEPHONY_STATE - Required subscriber permissions: ohos.permission.GET_TELEPHONY_STATE
## COMMON_EVENT_CELLULAR_DATA_STATE_CHANGED<sup>10+<sup> ## [COMMON_EVENT_CELLULAR_DATA_STATE_CHANGED<sup>10+<sup>](./common_event/commonEvent-telephony.md)
Indicates that the cellular data state has changed. Indicates that the cellular data state has changed.
- Value: **usual.event.CELLULAR_DATA_STATE_CHANGED** - Value: **usual.event.CELLULAR_DATA_STATE_CHANGED**
- Required subscriber permissions: none - Required subscriber permissions: none
## COMMON_EVENT_NETWORK_STATE_CHANGED<sup>10+<sup> ## [COMMON_EVENT_NETWORK_STATE_CHANGED<sup>10+<sup>](./common_event/commonEvent-telephony.md)
Indicates that the network state has changed. Indicates that the network state has changed.
- Value: **usual.event.NETWORK_STATE_CHANGED** - Value: **usual.event.NETWORK_STATE_CHANGED**
- Required subscriber permissions: none - Required subscriber permissions: none
## COMMON_EVENT_SIGNAL_INFO_CHANGED<sup>10+<sup> ## [COMMON_EVENT_SIGNAL_INFO_CHANGED<sup>10+<sup>](./common_event/commonEvent-telephony.md)
Indicates that the signal information is updated. Indicates that the signal information is updated.
- Value: **usual.event.SIGNAL_INFO_CHANGED** - Value: **usual.event.SIGNAL_INFO_CHANGED**
- Required subscriber permissions: none - Required subscriber permissions: none
## COMMON_EVENT_INCOMING_CALL_MISSED<sup>10+<sup> ## [COMMON_EVENT_INCOMING_CALL_MISSED<sup>10+<sup>](./common_event/commonEvent-telephony.md)
Indicates a missed call. Indicates a missed call.
- Value: **usual.event.INCOMING_CALL_MISSED** - Value: **usual.event.INCOMING_CALL_MISSED**
- Required subscriber permissions: ohos.permission.GET_TELEPHONY_STATE - Required subscriber permissions: ohos.permission.GET_TELEPHONY_STATE
## COMMON_EVENT_RADIO_STATE_CHANGE<sup>10+<sup> ## [COMMON_EVENT_RADIO_STATE_CHANGE<sup>10+<sup>](./common_event/commonEvent-telephony.md)
Indicates that the power-on and power-off status of the modem has changed. Indicates that the power-on and power-off status of the modem has changed.
- Value: **usual.event.RADIO_STATE_CHANGE** - Value: **usual.event.RADIO_STATE_CHANGE**
......
# Common Events of the Telephony Subsystem
This document lists the common system events provided by the telephony subsystem to applications.
## COMMON_EVENT_SIM_STATE_CHANGED
Indicates that the SIM card status has changed.
- Value: usual.event.SIM_STATE_CHANGED
- Required subscriber permissions: none
When the there is a change in the SIM card status of the device, the event notification service is triggered to publish this event.
## COMMON_EVENT_SMS_RECEIVED_COMPLETED
Indicates that an SMS message is received.
- Value: usual.event.SMS_RECEIVED_COMPLETED
- Required subscriber permissions: ohos.permission.RECEIVE_SMS
When the device receives an SMS message, the event notification service is triggered to publish this event.
## COMMON_EVENT_SMS_EMERGENCY_CB_RECEIVE_COMPLETED
Indicates that an emergency cell broadcast message is received.
- Value: usual.event.SMS_EMERGENCY_CB_RECEIVE_COMPLETED
- Required subscriber permissions: ohos.permission.RECEIVE_SMS
When the device receives an emergency cell broadcast message, the event notification service is triggered to publish this event.
## COMMON_EVENT_SMS_CB_RECEIVE_COMPLETED
Indicates that a cell broadcast message is received.
- Value: usual.event.SMS_CB_RECEIVE_COMPLETED
- Required subscriber permissions: ohos.permission.RECEIVE_SMS
When the device receives a cell broadcast message, the event notification service is triggered to publish this event.
## COMMON_EVENT_STK_COMMAND
(Reserved, not supported yet) Indicates that an STK command is sent.
- Value: usual.event.STK_COMMAND
- Required subscriber permissions: none
When an STK command is sent, the event notification service is triggered to publish this event.
## COMMON_EVENT_STK_SESSION_END
(Reserved event, not supported currently) Indicates that an STK session has ended.
- Value: usual.event.STK_SESSION_END
- Required subscriber permissions: none
When an STK session ends, the event notification service is triggered to publish this event.
## COMMON_EVENT_STK_CARD_STATE_CHANGED
(Reserved event, not supported currently) Indicates that the STK card status has been updated.
- Value: usual.event.STK_CARD_STATE_CHANGED
- Required subscriber permissions: none
When the STK card status is updated, the event notification service is triggered to publish this event.
## COMMON_EVENT_STK_ALPHA_IDENTIFIER
(Reserved event, not supported currently) Indicates that an STK Alpha identifier is sent.
- Value: usual.event.STK_ALPHA_IDENTIFIER
- Required subscriber permissions: none
When an STK Alpha identifier is sent, the event notification service is triggered to publish this event.
## COMMON_EVENT_SMS_WAPPUSH_RECEIVE_COMPLETED
Indicates that a WAP push message is received.
- Value: usual.event.SMS_WAPPUSH_RECEIVE_COMPLETED
- Required subscriber permissions: ohos.permission.RECEIVE_SMS
When the device receives a WAP push message, the event notification service is triggered to publish this event.
## COMMON_EVENT_OPERATOR_CONFIG_CHANGED
Indicates that the carrier configuration has been updated.
- Value: usual.event.OPERATOR_CONFIG_CHANGED
- Required subscriber permissions: none
When the carrier configuration of the device is updated, the event notification service is triggered to publish this event.
## COMMON_EVENT_SIM_CARD_DEFAULT_SMS_SUBSCRIPTION_CHANGED
Indicates that the default primary SIM card for the SMS service has been updated.
- Value: usual.event.DEFAULT_SMS_SUBSCRIPTION_CHANGED
- Required subscriber permissions: none
When the default primary SIM card for the SMS service is updated, the event notification service is triggered to publish this event.
## COMMON_EVENT_SIM_CARD_DEFAULT_DATA_SUBSCRIPTION_CHANGED
Indicates that the default primary SIM card for the data service has been updated.
- Value: usual.event.DEFAULT_DATA_SUBSCRIPTION_CHANGED
- Required subscriber permissions: none
When the default primary SIM card for the data service is updated, the event notification service is triggered to release the system common event.
## COMMON_EVENT_SIM_CARD_DEFAULT_MAIN_SUBSCRIPTION_CHANGED
Indicates that the default primary SIM card of the device has been updated.
- Value: usual.event.SIM.DEFAULT_MAIN_SUBSCRIPTION_CHANGED
- Required subscriber permissions: none
When the default primary SIM card of the device is updated, the event notification service is triggered to publish this event.
## COMMON_EVENT_SIM_CARD_DEFAULT_VOICE_SUBSCRIPTION_CHANGED
When the default primary SIM card for the voice service is updated, the event notification service is triggered to publish this event.
- Value: usual.event.DEFAULT_VOICE_SUBSCRIPTION_CHANGED
- Required subscriber permissions: none
When the default primary SIM card for the voice service is updated, the event notification service is triggered to publish this event.
## COMMON_EVENT_CALL_STATE_CHANGED
Indicates that the call status has been updated.
- Value: usual.event.CALL_STATE_CHANGED
- Required subscriber permissions: ohos.permission.GET_TELEPHONY_STATE
When the call status of the device is updated, the event notification service is triggered to publish this event.
## COMMON_EVENT_CELLULAR_DATA_STATE_CHANGED
Indicates that the cellular data status has been updated.
- Value: usual.event.CELLULAR_DATA_STATE_CHANGED
- Required subscriber permissions: none
When the cellular data status of the device is updated, the event notification service is triggered to publish this event.
## COMMON_EVENT_NETWORK_STATE_CHANGED
Indicates that the network status has been updated.
- Value: usual.event.NETWORK_STATE_CHANGED
- Required subscriber permissions: none
When the network status of the device is updated, the event notification service is triggered to publish this event.
## COMMON_EVENT_SIGNAL_INFO_CHANGED
Indicates that the signal information has been updated.
- Value: usual.event.SIGNAL_INFO_CHANGED
- Required subscriber permissions: none
When the signal information of the device is updated, the event notification service is triggered to publish this event.
## COMMON_EVENT_INCOMING_CALL_MISSED
Indicates that an incoming call is missed.
- Value: usual.event.INCOMING_CALL_MISSED
- Required subscriber permissions: ohos.permission.GET_TELEPHONY_STATE
When an incoming call is missed on the device, the event notification service is triggered to publish this event.
## COMMON_EVENT_RADIO_STATE_CHANGE
Indicates that the radio status of the device has changed.
- Value: usual.event.RADIO_STATE_CHANGE
- Required subscriber permissions: none
When there is a change in the radio status of the device, the event notification service is triggered to publish this event.
## COMMON_EVENT_DIALER_SPECIAL_CODE
Indicates that a secret code is sent successfully.
- Value: usual.event.DIALER_SPECIAL_CODE
- Required subscriber permissions: none
When a secret code is successfully sent on the device, the event notification service is triggered to publish this event.
## COMMON_EVENT_AUDIO_QUALITY_CHANGE
Indicates that the audio quality has changed.
- Value: usual.event.AUDIO_QUALITY_CHANGE
- Required subscriber permissions: none
When there is a change in the audio quality of the device, the event notification service is triggered to publish this event.
...@@ -31,7 +31,7 @@ Marks the start of a timeslice trace task. ...@@ -31,7 +31,7 @@ Marks the start of a timeslice trace task.
| -------- | -------- | -------- | -------- | | -------- | -------- | -------- | -------- |
| name | string | Yes| Name of a timeslice trace task.| | name | string | Yes| Name of a timeslice trace task.|
| taskId | number | Yes| ID of a timeslice trace task.| | taskId | number | Yes| ID of a timeslice trace task.|
| expectedTime | number | No| Expected duration of the trace, in ms.| | expectedTime | number | No| Expected duration of the trace, in ms. By default, no value is passed. |
**Example** **Example**
......
...@@ -65,6 +65,9 @@ httpRequest.request( ...@@ -65,6 +65,9 @@ httpRequest.request(
); );
``` ```
> **NOTE**
> If the data in **console.info()** contains a newline character, the data will be truncated.
## http.createHttp ## http.createHttp
createHttp(): HttpRequest createHttp(): HttpRequest
...@@ -98,7 +101,7 @@ request(url: string, callback: AsyncCallback\<HttpResponse\>):void ...@@ -98,7 +101,7 @@ request(url: string, callback: AsyncCallback\<HttpResponse\>):void
Initiates an HTTP request to a given URL. This API uses an asynchronous callback to return the result. Initiates an HTTP request to a given URL. This API uses an asynchronous callback to return the result.
> **NOTE** > **NOTE**
> This API supports only transfer of data not greater than 5 MB. > This API supports only receiving of data not greater than 5 MB.
**Required permissions**: ohos.permission.INTERNET **Required permissions**: ohos.permission.INTERNET
...@@ -149,7 +152,7 @@ request(url: string, options: HttpRequestOptions, callback: AsyncCallback\<HttpR ...@@ -149,7 +152,7 @@ request(url: string, options: HttpRequestOptions, callback: AsyncCallback\<HttpR
Initiates an HTTP request containing specified options to a given URL. This API uses an asynchronous callback to return the result. Initiates an HTTP request containing specified options to a given URL. This API uses an asynchronous callback to return the result.
> **NOTE** > **NOTE**
> This API supports only transfer of data not greater than 5 MB. > This API supports only receiving of data not greater than 5 MB.
**Required permissions**: ohos.permission.INTERNET **Required permissions**: ohos.permission.INTERNET
...@@ -235,7 +238,7 @@ request(url: string, options? : HttpRequestOptions): Promise\<HttpResponse\> ...@@ -235,7 +238,7 @@ request(url: string, options? : HttpRequestOptions): Promise\<HttpResponse\>
Initiates an HTTP request containing specified options to a given URL. This API uses a promise to return the result. Initiates an HTTP request containing specified options to a given URL. This API uses a promise to return the result.
> **NOTE** > **NOTE**
> This API supports only transfer of data not greater than 5 MB. > This API supports only receiving of data not greater than 5 MB.
**Required permissions**: ohos.permission.INTERNET **Required permissions**: ohos.permission.INTERNET
...@@ -474,7 +477,7 @@ Initiates an HTTP request containing specified options to a given URL. This API ...@@ -474,7 +477,7 @@ Initiates an HTTP request containing specified options to a given URL. This API
**Return value** **Return value**
| Type | Description | | Type | Description |
| ------------------------------------- | -------------------------------- | | :------------------------------------- | :-------------------------------- |
| Promise\<[number](#responsecode)\> | Promise used to return the result.| | Promise\<[number](#responsecode)\> | Promise used to return the result.|
**Error codes** **Error codes**
...@@ -535,7 +538,7 @@ promise.then((data) => { ...@@ -535,7 +538,7 @@ promise.then((data) => {
}); });
``` ```
### on('headerReceive') ### on('headerReceive')<sup>(deprecated)</sup>
on(type: 'headerReceive', callback: AsyncCallback\<Object\>): void on(type: 'headerReceive', callback: AsyncCallback\<Object\>): void
...@@ -561,7 +564,7 @@ httpRequest.on('headerReceive', (data) => { ...@@ -561,7 +564,7 @@ httpRequest.on('headerReceive', (data) => {
}); });
``` ```
### off('headerReceive') ### off('headerReceive')<sup>(deprecated)</sup>
off(type: 'headerReceive', callback?: AsyncCallback\<Object\>): void off(type: 'headerReceive', callback?: AsyncCallback\<Object\>): void
...@@ -808,12 +811,12 @@ Specifies the type and value range of the optional parameters in the HTTP reques ...@@ -808,12 +811,12 @@ Specifies the type and value range of the optional parameters in the HTTP reques
| Name | Type | Mandatory| Description | | Name | Type | Mandatory| Description |
| -------------- | --------------------------------------------- | ---- | ------------------------------------------------------------ | | -------------- | --------------------------------------------- | ---- | ------------------------------------------------------------ |
| method | [RequestMethod](#requestmethod) | No | Request method. The default value is **GET**. | | method | [RequestMethod](#requestmethod) | No | Request method. The default value is **GET**. |
| extraData | string<sup>6+</sup> \| Object<sup>6+</sup> \| ArrayBuffer<sup>8+</sup> | No | Additional data for sending a request. This parameter is not used by default.<br>- If the HTTP request uses a POST or PUT method, this parameter serves as the content of the HTTP request and is encoded in UTF-8 format.<sup>6+</sup><br>- If the HTTP request uses the GET, OPTIONS, DELETE, TRACE, or CONNECT method, this parameter serves as a supplement to HTTP request parameters. Parameters of the string type need to be encoded before being passed to the HTTP request. Parameters of the object type do not need to be precoded and will be directly concatenated to the URL. Parameters of the ArrayBuffer type will not be concatenated to the URL.<sup>6+</sup> | | extraData | string<sup>6+</sup> \| Object<sup>6+</sup> \| ArrayBuffer<sup>8+</sup> | No | Additional data for sending a request. This parameter is not used by default.<br>- If the HTTP request uses a POST or PUT method, this parameter serves as the content of the HTTP request and is encoded in UTF-8 format. If **'Content-Type'** is **'application/x-www-form-urlencoded'**, the data in the request body must be encoded in the format of **key1=value1&key2=value2&key3=value3** after URL transcoding.<sup>6+</sup><br>- If the HTTP request uses the GET, OPTIONS, DELETE, TRACE, or CONNECT method, this parameter serves as a supplement to HTTP request parameters. Parameters of the string type need to be encoded before being passed to the HTTP request. Parameters of the object type do not need to be precoded and will be directly concatenated to the URL. Parameters of the ArrayBuffer type will not be concatenated to the URL.<sup>6+</sup> |
| expectDataType<sup>9+</sup> | [HttpDataType](#httpdatatype9) | No | Type of the returned data. This parameter is not used by default. If this parameter is set, the system returns the specified type of data preferentially.| | expectDataType<sup>9+</sup> | [HttpDataType](#httpdatatype9) | No | Type of the returned data. This parameter is not used by default. If this parameter is set, the system returns the specified type of data preferentially.|
| usingCache<sup>9+</sup> | boolean | No | Whether to use the cache. The default value is **true**. | | usingCache<sup>9+</sup> | boolean | No | Whether to use the cache. The default value is **true**. |
| priority<sup>9+</sup> | number | No | Priority. The value range is \[0, 1000]. The default value is **0**. | | priority<sup>9+</sup> | number | No | Priority. The value range is [1,1000]. The default value is **1**. |
| header | Object | No | HTTP request header. The default value is **{'Content-Type': 'application/json'}**. | | header | Object | No | HTTP request header. The default value is **{'Content-Type': 'application/json'}**. |
| readTimeout | number | No | Read timeout duration. The default value is **60000**, in ms. | | readTimeout | number | No | Read timeout duration. The default value is **60000**, in ms.<br>The value **0** indicates no timeout.|
| connectTimeout | number | No | Connection timeout interval. The default value is **60000**, in ms. | | connectTimeout | number | No | Connection timeout interval. The default value is **60000**, in ms. |
| usingProtocol<sup>9+</sup> | [HttpProtocol](#httpprotocol9) | No | Protocol. The default value is automatically specified by the system. | | usingProtocol<sup>9+</sup> | [HttpProtocol](#httpprotocol9) | No | Protocol. The default value is automatically specified by the system. |
| usingProxy<sup>10+</sup> | boolean \| Object | No | Whether to use HTTP proxy. The default value is **false**, which means not to use HTTP proxy.<br>- If **usingProxy** is of the **Boolean** type and the value is **true**, network proxy is used by default.<br>- If **usingProxy** is of the **object** type, the specified network proxy is used. | | usingProxy<sup>10+</sup> | boolean \| Object | No | Whether to use HTTP proxy. The default value is **false**, which means not to use HTTP proxy.<br>- If **usingProxy** is of the **Boolean** type and the value is **true**, network proxy is used by default.<br>- If **usingProxy** is of the **object** type, the specified network proxy is used. |
......
...@@ -15,7 +15,7 @@ import connection from '@ohos.net.connection' ...@@ -15,7 +15,7 @@ import connection from '@ohos.net.connection'
createNetConnection(netSpecifier?: NetSpecifier, timeout?: number): NetConnection createNetConnection(netSpecifier?: NetSpecifier, timeout?: number): NetConnection
Creates a **NetConnection** object. **netSpecifier** specifies the network, and **timeout** specifies the timeout interval in ms. **timeout** is configurable only when **netSpecifier** is specified. If neither of them is present, the default network is used. Creates a **NetConnection** object. **netSpecifier** specifies the network, and **timeout** specifies the timeout duration in ms. **timeout** is configurable only when **netSpecifier** is specified. If neither of them is present, the default network is used.
**System capability**: SystemCapability.Communication.NetManager.Core **System capability**: SystemCapability.Communication.NetManager.Core
...@@ -23,8 +23,8 @@ Creates a **NetConnection** object. **netSpecifier** specifies the network, and ...@@ -23,8 +23,8 @@ Creates a **NetConnection** object. **netSpecifier** specifies the network, and
| Name | Type | Mandatory| Description | | Name | Type | Mandatory| Description |
| ------------ | ----------------------------- | ---- | ------------------------------------------------------------ | | ------------ | ----------------------------- | ---- | ------------------------------------------------------------ |
| netSpecifier | [NetSpecifier](#netspecifier) | No | Network specifier. If this parameter is not set, the default network is used. | | netSpecifier | [NetSpecifier](#netspecifier) | No | Network specifier, which specifies the characteristics of a network. If this parameter is not set or is set to **undefined**, the default network is used. |
| timeout | number | No | Timeout interval for obtaining the network specified by **netSpecifier**. This parameter is valid only when **netSpecifier** is set.| | timeout | number | No | Timeout duration for obtaining the network specified by **netSpecifier**. This parameter is valid only when **netSpecifier** is specified. The default value is **0** if **netSpecifier** is **undefined**.|
**Return value** **Return value**
...@@ -1840,7 +1840,7 @@ Defines the global HTTP proxy configuration of the network. ...@@ -1840,7 +1840,7 @@ Defines the global HTTP proxy configuration of the network.
| ------ | ------ | --- |------------------------- | | ------ | ------ | --- |------------------------- |
| host | string | No | Host name of the proxy server.| | host | string | No | Host name of the proxy server.|
| port | number | No | Host port.| | port | number | No | Host port.|
| exclusionList | Array<string> | No | List of hosts that do not use the proxy server.| | exclusionList | Array<string> | No | Exclusion list of hosts that do not use the proxy server. The length of the combined elements in the list cannot exceed 96 bytes.<br>For example, the length of **baidu.com,zhihu.com** is 20 bytes.|
## NetSpecifier ## NetSpecifier
......
...@@ -403,7 +403,7 @@ Registers an observer for NIC hot swap events. This API uses an asynchronous cal ...@@ -403,7 +403,7 @@ Registers an observer for NIC hot swap events. This API uses an asynchronous cal
| Name | Type | Mandatory| Description | | Name | Type | Mandatory| Description |
| -------- | --------------------------------------- | ---- | ---------- | | -------- | --------------------------------------- | ---- | ---------- |
| type | string | Yes | Event type. The value is **interfaceStateChange**.| | type | string | Yes | Event type. The value is **interfaceStateChange**.|
| callback | AsyncCallback\<{ iface: string, active: boolean }\> | Yes | Callback used to return the result.<br>**iface**: NIC name.<br>**active**: whether the NIC is active. The value **true** indicates that the NIC is active, and the value **false** indicates the opposite.| | callback | Callback\<{ iface: string, active: boolean }\> | Yes | Callback used to return the result.<br>**iface**: NIC name.<br>**active**: whether the NIC is active. The value **true** indicates that the NIC is active, and the value **false** indicates the opposite.|
**Error codes** **Error codes**
...@@ -416,8 +416,8 @@ Registers an observer for NIC hot swap events. This API uses an asynchronous cal ...@@ -416,8 +416,8 @@ Registers an observer for NIC hot swap events. This API uses an asynchronous cal
**Example** **Example**
```js ```js
ethernet.on('interfaceStateChange', (data) => { ethernet.on('interfaceStateChange', (data) => {
console.log('on interfaceSharingStateChange: ' + JSON.stringify(data)); console.log('on interfaceSharingStateChange: ' + JSON.stringify(data.iface) + JSON.stringify(data.active));
}); });
``` ```
...@@ -438,7 +438,7 @@ Unregisters the observer for NIC hot swap events. This API uses an asynchronous ...@@ -438,7 +438,7 @@ Unregisters the observer for NIC hot swap events. This API uses an asynchronous
| Name | Type | Mandatory| Description | | Name | Type | Mandatory| Description |
| -------- | --------------------------------------- | ---- | ---------- | | -------- | --------------------------------------- | ---- | ---------- |
| type | string | Yes | Event type. The value is **interfaceStateChange**.| | type | string | Yes | Event type. The value is **interfaceStateChange**.|
| callback | AsyncCallback\<{ iface: string, active: boolean }> | No | Callback used to return the result.<br>**iface**: NIC name.<br>**active**: whether the NIC is active. The value **true** indicates that the NIC is active, and the value **false** indicates the opposite.| | callback | Callback\<{ iface: string, active: boolean }> | No | Callback used to return the result.<br>**iface**: NIC name.<br>**active**: whether the NIC is active. The value **true** indicates that the NIC is active, and the value **false** indicates the opposite.|
**Error codes** **Error codes**
......
...@@ -12,9 +12,9 @@ The **policy** module provides APIs for managing network policies, through which ...@@ -12,9 +12,9 @@ The **policy** module provides APIs for managing network policies, through which
import policy from '@ohos.net.policy' import policy from '@ohos.net.policy'
``` ```
## policy.setBackgroundPolicy ## policy.setBackgroundAllowed
setBackgroundPolicy(isAllowed: boolean, callback: AsyncCallback\<void>): void setBackgroundAllowed(isAllowed: boolean, callback: AsyncCallback\<void>): void
Sets a background network policy. This API uses an asynchronous callback to return the result. Sets a background network policy. This API uses an asynchronous callback to return the result.
...@@ -42,18 +42,15 @@ Sets a background network policy. This API uses an asynchronous callback to retu ...@@ -42,18 +42,15 @@ Sets a background network policy. This API uses an asynchronous callback to retu
**Example** **Example**
```js ```js
policy.setBackgroundPolicy(Boolean(Number.parseInt(this.isBoolean))), (error, data) => { policy.setBackgroundAllowed(Boolean(Number.parseInt(this.isBoolean)), (error) => {
this.callBack(error, data);
console.log(JSON.stringify(error)) console.log(JSON.stringify(error))
console.log(JSON.stringify(data)) })
}
)
; ;
``` ```
## policy.setBackgroundPolicy ## policy.setBackgroundAllowed
setBackgroundPolicy(isAllowed: boolean): Promise\<void> setBackgroundAllowed(isAllowed: boolean): Promise\<void>
Sets a background network policy. This API uses a promise to return the result. Sets a background network policy. This API uses a promise to return the result.
...@@ -86,9 +83,8 @@ Sets a background network policy. This API uses a promise to return the result. ...@@ -86,9 +83,8 @@ Sets a background network policy. This API uses a promise to return the result.
**Example** **Example**
```js ```js
policy.setBackgroundPolicy(Boolean(Number.parseInt(this.isBoolean))).then(function (error, data) { policy.setBackgroundAllowed(Boolean(Number.parseInt(this.isBoolean))).then(function (error) {
console.log(JSON.stringify(error)) console.log(JSON.stringify(error))
console.log(JSON.stringify(data))
}) })
``` ```
...@@ -157,7 +153,6 @@ policy.isBackgroundAllowed().then(function (error, data) { ...@@ -157,7 +153,6 @@ policy.isBackgroundAllowed().then(function (error, data) {
console.log(JSON.stringify(error)) console.log(JSON.stringify(error))
console.log(JSON.stringify(data)) console.log(JSON.stringify(data))
}) })
``` ```
## policy.setPolicyByUid ## policy.setPolicyByUid
...@@ -194,8 +189,8 @@ Sets an application-specific network policy. This API uses an asynchronous callb ...@@ -194,8 +189,8 @@ Sets an application-specific network policy. This API uses an asynchronous callb
let param = { let param = {
uid: Number.parseInt(this.firstParam), policy: Number.parseInt(this.currentNetUidPolicy) uid: Number.parseInt(this.firstParam), policy: Number.parseInt(this.currentNetUidPolicy)
} }
policy.setPolicyByUid(Number.parseInt(this.firstParam), Number.parseInt(this.currentNetUidPolicy), (error, data) => { policy.setPolicyByUid(Number.parseInt(this.firstParam), Number.parseInt(this.currentNetUidPolicy), (error) => {
this.callBack(error, data); this.callBack(error);
}); });
``` ```
...@@ -238,11 +233,9 @@ Sets an application-specific network policy. This API uses a promise to return t ...@@ -238,11 +233,9 @@ Sets an application-specific network policy. This API uses a promise to return t
let param = { let param = {
uid: Number.parseInt(this.firstParam), policy: Number.parseInt(this.currentNetUidPolicy) uid: Number.parseInt(this.firstParam), policy: Number.parseInt(this.currentNetUidPolicy)
} }
policy.setPolicyByUid(Number.parseInt(this.firstParam), Number.parseInt(this.currentNetUidPolicy)).then(function (error, data) { policy.setPolicyByUid(Number.parseInt(this.firstParam), Number.parseInt(this.currentNetUidPolicy)).then(function (error) {
console.log(JSON.stringify(error)) console.log(JSON.stringify(error))
console.log(JSON.stringify(data))
}) })
``` ```
## policy.getPolicyByUid ## policy.getPolicyByUid
...@@ -319,7 +312,6 @@ policy.getPolicyByUid(Number.parseInt(this.firstParam)).then(function (error, da ...@@ -319,7 +312,6 @@ policy.getPolicyByUid(Number.parseInt(this.firstParam)).then(function (error, da
console.log(JSON.stringify(error)) console.log(JSON.stringify(error))
console.log(JSON.stringify(data)) console.log(JSON.stringify(data))
}) })
``` ```
## policy.getUidsByPolicy ## policy.getUidsByPolicy
...@@ -396,7 +388,6 @@ policy.getUidsByPolicy(Number.parseInt(this.firstParam)).then(function (error, d ...@@ -396,7 +388,6 @@ policy.getUidsByPolicy(Number.parseInt(this.firstParam)).then(function (error, d
console.log(JSON.stringify(error)) console.log(JSON.stringify(error))
console.log(JSON.stringify(data)) console.log(JSON.stringify(data))
}) })
``` ```
## policy.getNetQuotaPolicies ## policy.getNetQuotaPolicies
...@@ -509,8 +500,8 @@ let param = { ...@@ -509,8 +500,8 @@ let param = {
}; };
this.netQuotaPolicyList.push(param); this.netQuotaPolicyList.push(param);
policy.setNetQuotaPolicies(this.netQuotaPolicyList, (error, data) => { policy.setNetQuotaPolicies(this.netQuotaPolicyList, (error) => {
this.callBack(error, data); console.log(JSON.stringify(error))
}); });
``` ```
...@@ -563,9 +554,8 @@ let param = { ...@@ -563,9 +554,8 @@ let param = {
}; };
this.netQuotaPolicyList.push(param); this.netQuotaPolicyList.push(param);
policy.setNetQuotaPolicies(this.netQuotaPolicyList).then(function (error, data) { policy.setNetQuotaPolicies(this.netQuotaPolicyList).then(function (error) {
console.log(JSON.stringify(error)) console.log(JSON.stringify(error))
console.log(JSON.stringify(data))
}) })
``` ```
...@@ -600,8 +590,8 @@ Restores all the policies (cellular network, background network, firewall, and a ...@@ -600,8 +590,8 @@ Restores all the policies (cellular network, background network, firewall, and a
```js ```js
this.firstParam = iccid; this.firstParam = iccid;
policy.restoreAllPolicies(this.firstParam, (error, data) => { policy.restoreAllPolicies(this.firstParam, (error) => {
this.callBack(error, data); console.log(JSON.stringify(error))
}); });
``` ```
...@@ -641,11 +631,9 @@ Restores all the policies (cellular network, background network, firewall, and a ...@@ -641,11 +631,9 @@ Restores all the policies (cellular network, background network, firewall, and a
```js ```js
this.firstParam = iccid; this.firstParam = iccid;
policy.restoreAllPolicies(this.firstParam).then(function (error, data) { policy.restoreAllPolicies(this.firstParam).then(function (error) {
console.log(JSON.stringify(error)) console.log(JSON.stringify(error))
console.log(JSON.stringify(data))
}) })
``` ```
## policy.isUidNetAllowed ## policy.isUidNetAllowed
...@@ -679,7 +667,6 @@ Checks whether an application is allowed to access metered networks. This API us ...@@ -679,7 +667,6 @@ Checks whether an application is allowed to access metered networks. This API us
**Example** **Example**
```js ```js
let param = { let param = {
uid: Number.parseInt(this.firstParam), isMetered: Boolean(Number.parseInt(this.isBoolean)) uid: Number.parseInt(this.firstParam), isMetered: Boolean(Number.parseInt(this.isBoolean))
} }
...@@ -724,7 +711,6 @@ Checks whether an application is allowed to access metered networks. This API us ...@@ -724,7 +711,6 @@ Checks whether an application is allowed to access metered networks. This API us
**Example** **Example**
```js ```js
let param = { let param = {
uid: Number.parseInt(this.firstParam), isMetered: Boolean(Number.parseInt(this.isBoolean)) uid: Number.parseInt(this.firstParam), isMetered: Boolean(Number.parseInt(this.isBoolean))
} }
...@@ -732,7 +718,6 @@ policy.isUidNetAllowed(Number.parseInt(this.firstParam), Boolean(Number.parseInt ...@@ -732,7 +718,6 @@ policy.isUidNetAllowed(Number.parseInt(this.firstParam), Boolean(Number.parseInt
console.log(JSON.stringify(error)) console.log(JSON.stringify(error))
console.log(JSON.stringify(data)) console.log(JSON.stringify(data))
}) })
``` ```
## policy.isUidNetAllowed ## policy.isUidNetAllowed
...@@ -766,7 +751,6 @@ Checks whether an application is allowed to access the given network. This API u ...@@ -766,7 +751,6 @@ Checks whether an application is allowed to access the given network. This API u
**Example** **Example**
```js ```js
let param = { let param = {
uid: Number.parseInt(this.firstParam), iface: this.secondParam uid: Number.parseInt(this.firstParam), iface: this.secondParam
} }
...@@ -818,7 +802,6 @@ policy.isUidNetAllowed(Number.parseInt(this.firstParam), this.secondParam).then( ...@@ -818,7 +802,6 @@ policy.isUidNetAllowed(Number.parseInt(this.firstParam), this.secondParam).then(
console.log(JSON.stringify(error)) console.log(JSON.stringify(error))
console.log(JSON.stringify(data)) console.log(JSON.stringify(data))
}) })
``` ```
## policy.setDeviceIdleAllowList ## policy.setDeviceIdleAllowList
...@@ -855,8 +838,8 @@ Sets whether to add an application to the device idle allowlist. This API uses a ...@@ -855,8 +838,8 @@ Sets whether to add an application to the device idle allowlist. This API uses a
let param = { let param = {
uid: Number.parseInt(this.firstParam), isAllowed: Boolean(Number.parseInt(this.isBoolean)) uid: Number.parseInt(this.firstParam), isAllowed: Boolean(Number.parseInt(this.isBoolean))
} }
policy.setDeviceIdleAllowList(Number.parseInt(this.firstParam), Boolean(Number.parseInt(this.isBoolean)), (error, data) => { policy.setDeviceIdleAllowList(Number.parseInt(this.firstParam), Boolean(Number.parseInt(this.isBoolean)), (error) => {
this.callBack(error, data); console.log(JSON.stringify(error))
}); });
``` ```
...@@ -899,11 +882,9 @@ Sets whether to add an application to the device idle allowlist. This API uses a ...@@ -899,11 +882,9 @@ Sets whether to add an application to the device idle allowlist. This API uses a
let param = { let param = {
uid: Number.parseInt(this.firstParam), isAllowed: Boolean(Number.parseInt(this.isBoolean)) uid: Number.parseInt(this.firstParam), isAllowed: Boolean(Number.parseInt(this.isBoolean))
} }
policy.setDeviceIdleAllowList(Number.parseInt(this.firstParam), Boolean(Number.parseInt(this.isBoolean))).then(function (error, data) { policy.setDeviceIdleAllowList(Number.parseInt(this.firstParam), Boolean(Number.parseInt(this.isBoolean))).then(function (error) {
console.log(JSON.stringify(error)) console.log(JSON.stringify(error))
console.log(JSON.stringify(data))
}) })
``` ```
## policy.getDeviceIdleAllowList ## policy.getDeviceIdleAllowList
...@@ -1080,8 +1061,8 @@ Restores all the policies (cellular network, background network, firewall, and a ...@@ -1080,8 +1061,8 @@ Restores all the policies (cellular network, background network, firewall, and a
```js ```js
this.firstParam = iccid this.firstParam = iccid
policy.resetPolicies(this.firstParam, (error, data) => { policy.resetPolicies(this.firstParam, (error) => {
this.callBack(error, data); console.log(JSON.stringify(error))
}); });
``` ```
...@@ -1124,11 +1105,9 @@ policy.getUidsByPolicy(Number.parseInt(this.firstParam)).then(function (error, d ...@@ -1124,11 +1105,9 @@ policy.getUidsByPolicy(Number.parseInt(this.firstParam)).then(function (error, d
}) })
this.firstParam = iccid this.firstParam = iccid
policy.resetPolicies(this.firstParam).then(function (error, data) { policy.resetPolicies(this.firstParam).then(function (error) {
console.log(JSON.stringify(error)) console.log(JSON.stringify(error))
console.log(JSON.stringify(data))
}) })
``` ```
## policy.updateRemindPolicy ## policy.updateRemindPolicy
...@@ -1166,8 +1145,8 @@ Updates a reminder policy. This API uses an asynchronous callback to return the ...@@ -1166,8 +1145,8 @@ Updates a reminder policy. This API uses an asynchronous callback to return the
let param = { let param = {
netType: Number.parseInt(this.netType), iccid: this.firstParam, remindType: this.currentRemindType netType: Number.parseInt(this.netType), iccid: this.firstParam, remindType: this.currentRemindType
} }
policy.updateRemindPolicy(Number.parseInt(this.netType), this.firstParam, Number.parseInt(this.currentRemindType), (error, data) => { policy.updateRemindPolicy(Number.parseInt(this.netType), this.firstParam, Number.parseInt(this.currentRemindType), (error) => {
this.callBack(error, data); console.log(JSON.stringify(error))
}); });
``` ```
...@@ -1211,11 +1190,9 @@ Updates a reminder policy. This API uses a promise to return the result. ...@@ -1211,11 +1190,9 @@ Updates a reminder policy. This API uses a promise to return the result.
let param = { let param = {
netType: Number.parseInt(this.netType), iccid: this.firstParam, remindType: this.currentRemindType netType: Number.parseInt(this.netType), iccid: this.firstParam, remindType: this.currentRemindType
} }
policy.updateRemindPolicy(Number.parseInt(this.netType), this.firstParam, Number.parseInt(this.currentRemindType)).then(function (error, data) { policy.updateRemindPolicy(Number.parseInt(this.netType), this.firstParam, Number.parseInt(this.currentRemindType)).then(function (error) {
console.log(JSON.stringify(error)) console.log(JSON.stringify(error))
console.log(JSON.stringify(data))
}) })
``` ```
## policy.setPowerSaveAllowList ## policy.setPowerSaveAllowList
...@@ -1252,8 +1229,8 @@ Sets whether to add an application to the power-saving allowlist. This API uses ...@@ -1252,8 +1229,8 @@ Sets whether to add an application to the power-saving allowlist. This API uses
let param = { let param = {
uid: Number.parseInt(this.firstParam), isAllowed: Boolean(Number.parseInt(this.isBoolean)) uid: Number.parseInt(this.firstParam), isAllowed: Boolean(Number.parseInt(this.isBoolean))
} }
policy.setPowerSaveAllowList(Number.parseInt(this.firstParam), Boolean(Number.parseInt(this.isBoolean)), (error, data) => { policy.setPowerSaveAllowList(Number.parseInt(this.firstParam), Boolean(Number.parseInt(this.isBoolean)), (error) => {
this.callBack(error, data); console.log(JSON.stringify(error))
}); });
``` ```
...@@ -1296,11 +1273,9 @@ Sets whether to add an application to the power-saving allowlist. This API uses ...@@ -1296,11 +1273,9 @@ Sets whether to add an application to the power-saving allowlist. This API uses
let param = { let param = {
uid: Number.parseInt(this.firstParam), isAllowed: Boolean(Number.parseInt(this.isBoolean)) uid: Number.parseInt(this.firstParam), isAllowed: Boolean(Number.parseInt(this.isBoolean))
} }
policy.setPowerSaveAllowList(Number.parseInt(this.firstParam), Boolean(Number.parseInt(this.isBoolean))).then(function (error, data) { policy.setPowerSaveAllowList(Number.parseInt(this.firstParam), Boolean(Number.parseInt(this.isBoolean))).then(function (error) {
console.log(JSON.stringify(error)) console.log(JSON.stringify(error))
console.log(JSON.stringify(data))
}) })
``` ```
## policy.getPowerSaveAllowList ## policy.getPowerSaveAllowList
......
...@@ -42,6 +42,9 @@ bind(address: NetAddress, callback: AsyncCallback\<void\>): void ...@@ -42,6 +42,9 @@ bind(address: NetAddress, callback: AsyncCallback\<void\>): void
Binds the IP address and port number. The port number can be specified or randomly allocated by the system. This API uses an asynchronous callback to return the result. Binds the IP address and port number. The port number can be specified or randomly allocated by the system. This API uses an asynchronous callback to return the result.
> **NOTE**
> This API is used for the client to create a socket.
**Required permissions**: ohos.permission.INTERNET **Required permissions**: ohos.permission.INTERNET
**System capability**: SystemCapability.Communication.NetStack **System capability**: SystemCapability.Communication.NetStack
...@@ -64,7 +67,7 @@ Binds the IP address and port number. The port number can be specified or random ...@@ -64,7 +67,7 @@ Binds the IP address and port number. The port number can be specified or random
```js ```js
let udp = socket.constructUDPSocketInstance(); let udp = socket.constructUDPSocketInstance();
udp.bind({address: '192.168.xx.xxx', port: xxxx, family: 1}, err => { udp.bind({ address: '192.168.xx.xxx', port: xxxx, family: 1 }, err => {
if (err) { if (err) {
console.log('bind fail'); console.log('bind fail');
return; return;
...@@ -79,6 +82,9 @@ bind(address: NetAddress): Promise\<void\> ...@@ -79,6 +82,9 @@ bind(address: NetAddress): Promise\<void\>
Binds the IP address and port number. The port number can be specified or randomly allocated by the system. This API uses a promise to return the result. Binds the IP address and port number. The port number can be specified or randomly allocated by the system. This API uses a promise to return the result.
> **NOTE**
> This API is used for the client to create a socket.
**Required permissions**: ohos.permission.INTERNET **Required permissions**: ohos.permission.INTERNET
**System capability**: SystemCapability.Communication.NetStack **System capability**: SystemCapability.Communication.NetStack
...@@ -106,7 +112,7 @@ Binds the IP address and port number. The port number can be specified or random ...@@ -106,7 +112,7 @@ Binds the IP address and port number. The port number can be specified or random
```js ```js
let udp = socket.constructUDPSocketInstance(); let udp = socket.constructUDPSocketInstance();
let promise = udp.bind({address: '192.168.xx.xxx', port: 8080, family: 1}); let promise = udp.bind({ address: '192.168.xx.xxx', port: 8080, family: 1 });
promise.then(() => { promise.then(() => {
console.log('bind success'); console.log('bind success');
}).catch(err => { }).catch(err => {
...@@ -335,7 +341,7 @@ Obtains the status of the UDPSocket connection. This API uses a promise to retur ...@@ -335,7 +341,7 @@ Obtains the status of the UDPSocket connection. This API uses a promise to retur
```js ```js
let udp = socket.constructUDPSocketInstance(); let udp = socket.constructUDPSocketInstance();
let promise = udp.bind({address: '192.168.xx.xxx', port: xxxx, family: 1}); let promise = udp.bind({ address: '192.168.xx.xxx', port: xxxx, family: 1 });
promise.then(err => { promise.then(err => {
if (err) { if (err) {
console.log('bind fail'); console.log('bind fail');
...@@ -382,7 +388,7 @@ Sets other attributes of the UDPSocket connection. This API uses an asynchronous ...@@ -382,7 +388,7 @@ Sets other attributes of the UDPSocket connection. This API uses an asynchronous
```js ```js
let udp = socket.constructUDPSocketInstance(); let udp = socket.constructUDPSocketInstance();
udp.bind({address: '192.168.xx.xxx', port: xxxx, family: 1}, err => { udp.bind({ address: '192.168.xx.xxx', port: xxxx, family: 1 }, err => {
if (err) { if (err) {
console.log('bind fail'); console.log('bind fail');
return; return;
...@@ -440,7 +446,7 @@ Sets other attributes of the UDPSocket connection. This API uses a promise to re ...@@ -440,7 +446,7 @@ Sets other attributes of the UDPSocket connection. This API uses a promise to re
```js ```js
let udp = socket.constructUDPSocketInstance(); let udp = socket.constructUDPSocketInstance();
let promise = udp.bind({address: '192.168.xx.xxx', port: xxxx, family: 1}); let promise = udp.bind({ address: '192.168.xx.xxx', port: xxxx, family: 1 });
promise.then(() => { promise.then(() => {
console.log('bind success'); console.log('bind success');
let promise1 = udp.setExtraOptions({ let promise1 = udp.setExtraOptions({
...@@ -480,7 +486,14 @@ Enables listening for message receiving events of the UDPSocket connection. This ...@@ -480,7 +486,14 @@ Enables listening for message receiving events of the UDPSocket connection. This
```js ```js
let udp = socket.constructUDPSocketInstance(); let udp = socket.constructUDPSocketInstance();
udp.on('message', value => { udp.on('message', value => {
console.log("on message, message:" + value.message + ", remoteInfo:" + value.remoteInfo); for (var i = 0; i < value.message.length; i++) {
let messages = value.message[i]
let message = String.fromCharCode(messages);
let messageView = '';
messageView += item;
}
console.log('on message message: ' + JSON.stringify(messageView));
console.log('remoteInfo: ' + JSON.stringify(value.remoteInfo));
}); });
``` ```
...@@ -507,7 +520,14 @@ Disables listening for message receiving events of the UDPSocket connection. Thi ...@@ -507,7 +520,14 @@ Disables listening for message receiving events of the UDPSocket connection. Thi
```js ```js
let udp = socket.constructUDPSocketInstance(); let udp = socket.constructUDPSocketInstance();
let callback = value => { let callback = value => {
console.log("on message, message:" + value.message + ", remoteInfo:" + value.remoteInfo); for (var i = 0; i < value.message.length; i++) {
let messages = value.message[i]
let message = String.fromCharCode(messages);
let messageView = '';
messageView += item;
}
console.log('on message message: ' + JSON.stringify(messageView));
console.log('remoteInfo: ' + JSON.stringify(value.remoteInfo));
} }
udp.on('message', callback); udp.on('message', callback);
// You can pass the callback of the on method to cancel listening for a certain type of callback. If you do not pass the callback, you will cancel listening for all callbacks. // You can pass the callback of the on method to cancel listening for a certain type of callback. If you do not pass the callback, you will cancel listening for all callbacks.
...@@ -733,6 +753,9 @@ bind(address: NetAddress, callback: AsyncCallback\<void\>): void ...@@ -733,6 +753,9 @@ bind(address: NetAddress, callback: AsyncCallback\<void\>): void
Binds the IP address and port number. The port number can be specified or randomly allocated by the system. This API uses an asynchronous callback to return the result. Binds the IP address and port number. The port number can be specified or randomly allocated by the system. This API uses an asynchronous callback to return the result.
> **NOTE**
> This API is used for the client to create a socket.
**Required permissions**: ohos.permission.INTERNET **Required permissions**: ohos.permission.INTERNET
**System capability**: SystemCapability.Communication.NetStack **System capability**: SystemCapability.Communication.NetStack
...@@ -755,7 +778,7 @@ Binds the IP address and port number. The port number can be specified or random ...@@ -755,7 +778,7 @@ Binds the IP address and port number. The port number can be specified or random
```js ```js
let tcp = socket.constructTCPSocketInstance(); let tcp = socket.constructTCPSocketInstance();
tcp.bind({address: '192.168.xx.xxx', port: xxxx, family: 1}, err => { tcp.bind({ address: '192.168.xx.xxx', port: xxxx, family: 1 }, err => {
if (err) { if (err) {
console.log('bind fail'); console.log('bind fail');
return; return;
...@@ -770,6 +793,9 @@ bind(address: NetAddress): Promise\<void\> ...@@ -770,6 +793,9 @@ bind(address: NetAddress): Promise\<void\>
Binds the IP address and port number. The port number can be specified or randomly allocated by the system. This API uses a promise to return the result. Binds the IP address and port number. The port number can be specified or randomly allocated by the system. This API uses a promise to return the result.
> **NOTE**
> This API is used for the client to create a socket.
**Required permissions**: ohos.permission.INTERNET **Required permissions**: ohos.permission.INTERNET
**System capability**: SystemCapability.Communication.NetStack **System capability**: SystemCapability.Communication.NetStack
...@@ -797,7 +823,7 @@ Binds the IP address and port number. The port number can be specified or random ...@@ -797,7 +823,7 @@ Binds the IP address and port number. The port number can be specified or random
```js ```js
let tcp = socket.constructTCPSocketInstance(); let tcp = socket.constructTCPSocketInstance();
let promise = tcp.bind({address: '192.168.xx.xxx', port: xxxx, family: 1}); let promise = tcp.bind({ address: '192.168.xx.xxx', port: xxxx, family: 1 });
promise.then(() => { promise.then(() => {
console.log('bind success'); console.log('bind success');
}).catch(err => { }).catch(err => {
...@@ -836,7 +862,7 @@ Sets up a connection to the specified IP address and port number. This API uses ...@@ -836,7 +862,7 @@ Sets up a connection to the specified IP address and port number. This API uses
```js ```js
let tcp = socket.constructTCPSocketInstance(); let tcp = socket.constructTCPSocketInstance();
tcp.connect({address: {address: '192.168.xx.xxx', port: xxxx, family: 1}, timeout: 6000}, err => { tcp.connect({ address: { address: '192.168.xx.xxx', port: xxxx, family: 1 }, timeout: 6000 }, err => {
if (err) { if (err) {
console.log('connect fail'); console.log('connect fail');
return; return;
...@@ -878,7 +904,7 @@ Sets up a connection to the specified IP address and port number. This API uses ...@@ -878,7 +904,7 @@ Sets up a connection to the specified IP address and port number. This API uses
```js ```js
let tcp = socket.constructTCPSocketInstance(); let tcp = socket.constructTCPSocketInstance();
let promise = tcp.connect({address: {address: '192.168.xx.xxx', port: xxxx, family: 1}, timeout: 6000}); let promise = tcp.connect({ address: { address: '192.168.xx.xxx', port: xxxx, family: 1 }, timeout: 6000 });
promise.then(() => { promise.then(() => {
console.log('connect success') console.log('connect success')
}).catch(err => { }).catch(err => {
...@@ -917,7 +943,7 @@ Sends data over a TCPSocket connection. This API uses an asynchronous callback t ...@@ -917,7 +943,7 @@ Sends data over a TCPSocket connection. This API uses an asynchronous callback t
```js ```js
let tcp = socket.constructTCPSocketInstance(); let tcp = socket.constructTCPSocketInstance();
tcp.connect({address: {address: '192.168.xx.xxx', port: xxxx, family: 1}, timeout: 6000}, () => { tcp.connect({ address: { address: '192.168.xx.xxx', port: xxxx, family: 1 }, timeout: 6000 }, () => {
console.log('connect success'); console.log('connect success');
tcp.send({ tcp.send({
data: 'Hello, server!' data: 'Hello, server!'
...@@ -968,7 +994,7 @@ Sends data over a TCPSocket connection. This API uses a promise to return the re ...@@ -968,7 +994,7 @@ Sends data over a TCPSocket connection. This API uses a promise to return the re
```js ```js
let tcp = socket.constructTCPSocketInstance(); let tcp = socket.constructTCPSocketInstance();
let promise1 = tcp.connect({address: {address: '192.168.xx.xxx', port: xxxx, family: 1}, timeout: 6000}); let promise1 = tcp.connect({ address: { address: '192.168.xx.xxx', port: xxxx, family: 1 }, timeout: 6000 });
promise1.then(() => { promise1.then(() => {
console.log('connect success'); console.log('connect success');
let promise2 = tcp.send({ let promise2 = tcp.send({
...@@ -1082,7 +1108,7 @@ Obtains the remote address of a socket connection. This API uses an asynchronous ...@@ -1082,7 +1108,7 @@ Obtains the remote address of a socket connection. This API uses an asynchronous
```js ```js
let tcp = socket.constructTCPSocketInstance(); let tcp = socket.constructTCPSocketInstance();
tcp.connect({address: {address: '192.168.xx.xxx', port: xxxx, family: 1}, timeout: 6000}, () => { tcp.connect({ address: { address: '192.168.xx.xxx', port: xxxx, family: 1 }, timeout: 6000 }, () => {
console.log('connect success'); console.log('connect success');
tcp.getRemoteAddress((err, data) => { tcp.getRemoteAddress((err, data) => {
if (err) { if (err) {
...@@ -1123,7 +1149,7 @@ Obtains the remote address of a socket connection. This API uses a promise to re ...@@ -1123,7 +1149,7 @@ Obtains the remote address of a socket connection. This API uses a promise to re
```js ```js
let tcp = socket.constructTCPSocketInstance(); let tcp = socket.constructTCPSocketInstance();
let promise1 = tcp.connect({address: {address: '192.168.xx.xxx', port: xxxx, family: 1}, timeout: 6000}); let promise1 = tcp.connect({ address: { address: '192.168.xx.xxx', port: xxxx, family: 1 }, timeout: 6000 });
promise1.then(() => { promise1.then(() => {
console.log('connect success'); console.log('connect success');
let promise2 = tcp.getRemoteAddress(); let promise2 = tcp.getRemoteAddress();
...@@ -1166,7 +1192,7 @@ Obtains the status of the TCPSocket connection. This API uses an asynchronous ca ...@@ -1166,7 +1192,7 @@ Obtains the status of the TCPSocket connection. This API uses an asynchronous ca
```js ```js
let tcp = socket.constructTCPSocketInstance(); let tcp = socket.constructTCPSocketInstance();
let promise = tcp.connect({address: {address: '192.168.xx.xxx', port: xxxx, family: 1}, timeout: 6000}, () => { let promise = tcp.connect({ address: { address: '192.168.xx.xxx', port: xxxx, family: 1 }, timeout: 6000 }, () => {
console.log('connect success'); console.log('connect success');
tcp.getState((err, data) => { tcp.getState((err, data) => {
if (err) { if (err) {
...@@ -1207,7 +1233,7 @@ Obtains the status of the TCPSocket connection. This API uses a promise to retur ...@@ -1207,7 +1233,7 @@ Obtains the status of the TCPSocket connection. This API uses a promise to retur
```js ```js
let tcp = socket.constructTCPSocketInstance(); let tcp = socket.constructTCPSocketInstance();
let promise = tcp.connect({address: {address: '192.168.xx.xxx', port: xxxx, family: 1}, timeout: 6000}); let promise = tcp.connect({ address: { address: '192.168.xx.xxx', port: xxxx, family: 1 }, timeout: 6000 });
promise.then(() => { promise.then(() => {
console.log('connect success'); console.log('connect success');
let promise1 = tcp.getState(); let promise1 = tcp.getState();
...@@ -1252,13 +1278,13 @@ Sets other properties of the TCPSocket connection. This API uses an asynchronous ...@@ -1252,13 +1278,13 @@ Sets other properties of the TCPSocket connection. This API uses an asynchronous
```js ```js
let tcp = socket.constructTCPSocketInstance(); let tcp = socket.constructTCPSocketInstance();
let promise = tcp.connect({address: {address: '192.168.xx.xxx', port: xxxx, family: 1}, timeout: 6000}, () => { let promise = tcp.connect({ address: { address: '192.168.xx.xxx', port: xxxx, family: 1 }, timeout: 6000 }, () => {
console.log('connect success'); console.log('connect success');
tcp.setExtraOptions({ tcp.setExtraOptions({
keepAlive: true, keepAlive: true,
OOBInline: true, OOBInline: true,
TCPNoDelay: true, TCPNoDelay: true,
socketLinger: {on: true, linger: 10}, socketLinger: { on: true, linger: 10 },
receiveBufferSize: 1000, receiveBufferSize: 1000,
sendBufferSize: 1000, sendBufferSize: 1000,
reuseAddress: true, reuseAddress: true,
...@@ -1309,14 +1335,14 @@ Sets other properties of the TCPSocket connection. This API uses a promise to re ...@@ -1309,14 +1335,14 @@ Sets other properties of the TCPSocket connection. This API uses a promise to re
```js ```js
let tcp = socket.constructTCPSocketInstance(); let tcp = socket.constructTCPSocketInstance();
let promise = tcp.connect({address: {address: '192.168.xx.xxx', port: xxxx, family: 1}, timeout: 6000}); let promise = tcp.connect({ address: { address: '192.168.xx.xxx', port: xxxx, family: 1 }, timeout: 6000 });
promise.then(() => { promise.then(() => {
console.log('connect success'); console.log('connect success');
let promise1 = tcp.setExtraOptions({ let promise1 = tcp.setExtraOptions({
keepAlive: true, keepAlive: true,
OOBInline: true, OOBInline: true,
TCPNoDelay: true, TCPNoDelay: true,
socketLinger: {on: true, linger: 10}, socketLinger: { on: true, linger: 10 },
receiveBufferSize: 1000, receiveBufferSize: 1000,
sendBufferSize: 1000, sendBufferSize: 1000,
reuseAddress: true, reuseAddress: true,
...@@ -1352,7 +1378,14 @@ Enables listening for message receiving events of the TCPSocket connection. This ...@@ -1352,7 +1378,14 @@ Enables listening for message receiving events of the TCPSocket connection. This
```js ```js
let tcp = socket.constructTCPSocketInstance(); let tcp = socket.constructTCPSocketInstance();
tcp.on('message', value => { tcp.on('message', value => {
console.log("on message, message:" + value.message + ", remoteInfo:" + value.remoteInfo) for (var i = 0; i < value.message.length; i++) {
let messages = value.message[i]
let message = String.fromCharCode(messages);
let messageView = '';
messageView += item;
}
console.log('on message message: ' + JSON.stringify(messageView));
console.log('remoteInfo: ' + JSON.stringify(value.remoteInfo));
}); });
``` ```
...@@ -1379,7 +1412,14 @@ Disables listening for message receiving events of the TCPSocket connection. Thi ...@@ -1379,7 +1412,14 @@ Disables listening for message receiving events of the TCPSocket connection. Thi
```js ```js
let tcp = socket.constructTCPSocketInstance(); let tcp = socket.constructTCPSocketInstance();
let callback = value => { let callback = value => {
console.log("on message, message:" + value.message + ", remoteInfo:" + value.remoteInfo); for (var i = 0; i < value.message.length; i++) {
let messages = value.message[i]
let message = String.fromCharCode(messages);
let messageView = '';
messageView += item;
}
console.log('on message message: ' + JSON.stringify(messageView));
console.log('remoteInfo: ' + JSON.stringify(value.remoteInfo));
} }
tcp.on('message', callback); tcp.on('message', callback);
// You can pass the callback of the on method to cancel listening for a certain type of callback. If you do not pass the callback, you will cancel listening for all callbacks. // You can pass the callback of the on method to cancel listening for a certain type of callback. If you do not pass the callback, you will cancel listening for all callbacks.
...@@ -1409,7 +1449,7 @@ let tcp = socket.constructTCPSocketInstance(); ...@@ -1409,7 +1449,7 @@ let tcp = socket.constructTCPSocketInstance();
tcp.on('connect', () => { tcp.on('connect', () => {
console.log("on connect success") console.log("on connect success")
}); });
tcp.on('close', data => { tcp.on('close', () => {
console.log("on close success") console.log("on close success")
}); });
``` ```
...@@ -1605,7 +1645,7 @@ Binds the IP address and port number. This API uses an asynchronous callback to ...@@ -1605,7 +1645,7 @@ Binds the IP address and port number. This API uses an asynchronous callback to
**Example** **Example**
```js ```js
tls.bind({address: '192.168.xx.xxx', port: xxxx, family: 1}, err => { tls.bind({ address: '192.168.xx.xxx', port: xxxx, family: 1 }, err => {
if (err) { if (err) {
console.log('bind fail'); console.log('bind fail');
return; return;
...@@ -1648,7 +1688,7 @@ Binds the IP address and port number. This API uses a promise to return the resu ...@@ -1648,7 +1688,7 @@ Binds the IP address and port number. This API uses a promise to return the resu
**Example** **Example**
```js ```js
let promise = tls.bind({address: '192.168.xx.xxx', port: xxxx, family: 1}); let promise = tls.bind({ address: '192.168.xx.xxx', port: xxxx, family: 1 });
promise.then(() => { promise.then(() => {
console.log('bind success'); console.log('bind success');
}).catch(err => { }).catch(err => {
...@@ -1680,7 +1720,7 @@ Obtains the status of the TLSSocket connection. This API uses an asynchronous ca ...@@ -1680,7 +1720,7 @@ Obtains the status of the TLSSocket connection. This API uses an asynchronous ca
**Example** **Example**
```js ```js
let promise = tls.bind({address: '192.168.xx.xxx', port: xxxx, family: 1}, err => { let promise = tls.bind({ address: '192.168.xx.xxx', port: xxxx, family: 1 }, err => {
if (err) { if (err) {
console.log('bind fail'); console.log('bind fail');
return; return;
...@@ -1720,7 +1760,7 @@ Obtains the status of the TLSSocket connection. This API uses a promise to retur ...@@ -1720,7 +1760,7 @@ Obtains the status of the TLSSocket connection. This API uses a promise to retur
**Example** **Example**
```js ```js
let promiseBind = tls.bind({address: '192.168.xx.xxx', port: xxxx, family: 1}); let promiseBind = tls.bind({ address: '192.168.xx.xxx', port: xxxx, family: 1 });
promiseBind.then(() => { promiseBind.then(() => {
console.log('bind success'); console.log('bind success');
}).catch((err) => { }).catch((err) => {
...@@ -1760,7 +1800,7 @@ Sets other properties of the TCPSocket connection after successful binding of th ...@@ -1760,7 +1800,7 @@ Sets other properties of the TCPSocket connection after successful binding of th
**Example** **Example**
```js ```js
tls.bind({address: '192.168.xx.xxx', port: xxxx, family: 1}, err => { tls.bind({ address: '192.168.xx.xxx', port: xxxx, family: 1 }, err => {
if (err) { if (err) {
console.log('bind fail'); console.log('bind fail');
return; return;
...@@ -1772,7 +1812,7 @@ tls.setExtraOptions({ ...@@ -1772,7 +1812,7 @@ tls.setExtraOptions({
keepAlive: true, keepAlive: true,
OOBInline: true, OOBInline: true,
TCPNoDelay: true, TCPNoDelay: true,
socketLinger: {on: true, linger: 10}, socketLinger: { on: true, linger: 10 },
receiveBufferSize: 1000, receiveBufferSize: 1000,
sendBufferSize: 1000, sendBufferSize: 1000,
reuseAddress: true, reuseAddress: true,
...@@ -1784,7 +1824,6 @@ tls.setExtraOptions({ ...@@ -1784,7 +1824,6 @@ tls.setExtraOptions({
} }
console.log('setExtraOptions success'); console.log('setExtraOptions success');
}); });
``` ```
### setExtraOptions<sup>9+</sup> ### setExtraOptions<sup>9+</sup>
...@@ -1818,7 +1857,7 @@ Sets other properties of the TCPSocket connection after successful binding of th ...@@ -1818,7 +1857,7 @@ Sets other properties of the TCPSocket connection after successful binding of th
**Example** **Example**
```js ```js
tls.bind({address: '192.168.xx.xxx', port: xxxx, family: 1}, err => { tls.bind({ address: '192.168.xx.xxx', port: xxxx, family: 1 }, err => {
if (err) { if (err) {
console.log('bind fail'); console.log('bind fail');
return; return;
...@@ -1829,7 +1868,7 @@ let promise = tls.setExtraOptions({ ...@@ -1829,7 +1868,7 @@ let promise = tls.setExtraOptions({
keepAlive: true, keepAlive: true,
OOBInline: true, OOBInline: true,
TCPNoDelay: true, TCPNoDelay: true,
socketLinger: {on: true, linger: 10}, socketLinger: { on: true, linger: 10 },
receiveBufferSize: 1000, receiveBufferSize: 1000,
sendBufferSize: 1000, sendBufferSize: 1000,
reuseAddress: true, reuseAddress: true,
...@@ -1842,6 +1881,191 @@ promise.then(() => { ...@@ -1842,6 +1881,191 @@ promise.then(() => {
}); });
``` ```
### on('message')
on(type: 'message', callback: Callback<{message: ArrayBuffer, remoteInfo: SocketRemoteInfo}>): void;
Subscribes to **message** events of the TLSSocket connection. This API uses an asynchronous callback to return the result.
**System capability**: SystemCapability.Communication.NetStack
**Parameters**
| Name | Type | Mandatory| Description |
| -------- | ------------------------------------------------------------ | ---- | ----------------------------------------- |
| type | string | Yes | Type of the event to subscribe to.<br /> **message**: message receiving event|
| callback | Callback\<{message: ArrayBuffer, remoteInfo: [SocketRemoteInfo](#socketremoteinfo)}\> | Yes | Callback used to return the result.<br> **message**: received message.<br>**remoteInfo**: socket connection information.|
**Example**
```js
let tls = socket.constructTLSSocketInstance();
tls.on('message', value => {
for (var i = 0; i < value.message.length; i++) {
let messages = value.message[i]
let message = String.fromCharCode(messages);
let messageView = '';
messageView += item;
}
console.log('on message message: ' + JSON.stringify(messageView));
console.log('remoteInfo: ' + JSON.stringify(value.remoteInfo));
});
```
### off('message')
off(type: 'message', callback?: Callback\<{message: ArrayBuffer, remoteInfo: SocketRemoteInfo}\>): void
Unsubscribes from **message** events of the TLSSocket connection. This API uses an asynchronous callback to return the result.
> **NOTE**
> You can pass the callback of the **on** function if you want to cancel listening for a certain type of event. If you do not pass the callback, you will cancel listening for all events.
**System capability**: SystemCapability.Communication.NetStack
**Parameters**
| Name | Type | Mandatory| Description |
| -------- | ------------------------------------------------------------ | ---- | ----------------------------------------- |
| type | string | Yes | Type of the event to subscribe to.<br /> **message**: message receiving event|
| callback | Callback<{message: ArrayBuffer, remoteInfo: [SocketRemoteInfo](#socketremoteinfo)}> | No | Callback used to return the result. **message**: received message.<br>**remoteInfo**: socket connection information.|
**Example**
```js
let tls = socket.constructTLSSocketInstance();
let callback = value => {
for (var i = 0; i < value.message.length; i++) {
let messages = value.message[i]
let message = String.fromCharCode(messages);
let messageView = '';
messageView += item;
}
console.log('on message message: ' + JSON.stringify(messageView));
console.log('remoteInfo: ' + JSON.stringify(value.remoteInfo));
}
tls.on('message', callback);
// You can pass the callback of the on method to cancel listening for a certain type of callback. If you do not pass the callback, you will cancel listening for all callbacks.
tls.off('message', callback);
```
### on('connect' | 'close')
on(type: 'connect' | 'close', callback: Callback\<void\>): void
Enables listening for connection or close events of the TLSSocket connection. This API uses an asynchronous callback to return the result.
**System capability**: SystemCapability.Communication.NetStack
**Parameters**
| Name | Type | Mandatory| Description |
| -------- | ---------------- | ---- | ------------------------------------------------------------ |
| type | string | Yes | Type of the event to subscribe to.<br /><br>- **connect**: connection event<br>- **close**: close event|
| callback | Callback\<void\> | Yes | Callback used to return the result. |
**Example**
```js
let tls = socket.constructTLSSocketInstance();
tls.on('connect', () => {
console.log("on connect success")
});
tls.on('close', () => {
console.log("on close success")
});
```
### off('connect' | 'close')
off(type: 'connect' | 'close', callback?: Callback\<void\>): void
Disables listening for connection or close events of the TLSSocket connection. This API uses an asynchronous callback to return the result.
> **NOTE**
> You can pass the callback of the **on** function if you want to cancel listening for a certain type of event. If you do not pass the callback, you will cancel listening for all events.
**System capability**: SystemCapability.Communication.NetStack
**Parameters**
| Name | Type | Mandatory| Description |
| -------- | ---------------- | ---- | ------------------------------------------------------------ |
| type | string | Yes | Type of the event to subscribe to.<br /><br>- **connect**: connection event<br>- **close**: close event|
| callback | Callback\<void\> | No | Callback used to return the result. |
**Example**
```js
let tls = socket.constructTLSSocketInstance();
let callback1 = () => {
console.log("on connect success");
}
tls.on('connect', callback1);
// You can pass the callback of the on method to cancel listening for a certain type of callback. If you do not pass the callback, you will cancel listening for all callbacks.
tls.off('connect', callback1);
tls.off('connect');
let callback2 = () => {
console.log("on close success");
}
tls.on('close', callback2);
// You can pass the callback of the on method to cancel listening for a certain type of callback. If you do not pass the callback, you will cancel listening for all callbacks.
tls.off('close', callback2);
```
### on('error')
on(type: 'error', callback: ErrorCallback): void
Enables listening for error events of the TLSSocket connection. This API uses an asynchronous callback to return the result.
**System capability**: SystemCapability.Communication.NetStack
**Parameters**
| Name | Type | Mandatory| Description |
| -------- | ------------- | ---- | ------------------------------------ |
| type | string | Yes | Type of the event to subscribe to.<br /> **error**: error event|
| callback | ErrorCallback | Yes | Callback used to return the result. |
**Example**
```js
let tls = socket.constructTLSSocketInstance();
tls.on('error', err => {
console.log("on error, err:" + JSON.stringify(err))
});
```
### off('error')
off(type: 'error', callback?: ErrorCallback): void
Disables listening for error events of the TLSSocket connection. This API uses an asynchronous callback to return the result.
> **NOTE**
> You can pass the callback of the **on** function if you want to cancel listening for a certain type of event. If you do not pass the callback, you will cancel listening for all events.
**System capability**: SystemCapability.Communication.NetStack
**Parameters**
| Name | Type | Mandatory| Description |
| -------- | ------------- | ---- | ------------------------------------ |
| type | string | Yes | Type of the event to subscribe to.<br /> **error**: error event|
| callback | ErrorCallback | No | Callback used to return the result. |
**Example**
```js
let tls = socket.constructTLSSocketInstance();
let callback = err => {
console.log("on error, err:" + JSON.stringify(err));
}
tls.on('error', callback);
// You can pass the callback of the on method to cancel listening for a certain type of callback. If you do not pass the callback, you will cancel listening for all callbacks.
tls.off('error', callback);
```
### connect<sup>9+</sup> ### connect<sup>9+</sup>
connect(options: TLSConnectOptions, callback: AsyncCallback\<void\>): void connect(options: TLSConnectOptions, callback: AsyncCallback\<void\>): void
...@@ -1881,7 +2105,7 @@ Sets up a TLSSocket connection, and creates and initializes a TLS session after ...@@ -1881,7 +2105,7 @@ Sets up a TLSSocket connection, and creates and initializes a TLS session after
```js ```js
let tlsTwoWay = socket.constructTLSSocketInstance(); // Two way authentication let tlsTwoWay = socket.constructTLSSocketInstance(); // Two way authentication
tlsTwoWay.bind({address: '192.168.xxx.xxx', port: 8080, family: 1}, err => { tlsTwoWay.bind({ address: '192.168.xxx.xxx', port: 8080, family: 1 }, err => {
if (err) { if (err) {
console.log('bind fail'); console.log('bind fail');
return; return;
...@@ -1912,7 +2136,7 @@ tlsTwoWay.connect(options, (err, data) => { ...@@ -1912,7 +2136,7 @@ tlsTwoWay.connect(options, (err, data) => {
}); });
let tlsOneWay = socket.constructTLSSocketInstance(); // One way authentication let tlsOneWay = socket.constructTLSSocketInstance(); // One way authentication
tlsOneWay.bind({address: '192.168.xxx.xxx', port: 8080, family: 1}, err => { tlsOneWay.bind({ address: '192.168.xxx.xxx', port: 8080, family: 1 }, err => {
if (err) { if (err) {
console.log('bind fail'); console.log('bind fail');
return; return;
...@@ -1980,7 +2204,7 @@ Sets up a TLSSocket connection, and creates and initializes a TLS session after ...@@ -1980,7 +2204,7 @@ Sets up a TLSSocket connection, and creates and initializes a TLS session after
```js ```js
let tlsTwoWay = socket.constructTLSSocketInstance(); // Two way authentication let tlsTwoWay = socket.constructTLSSocketInstance(); // Two way authentication
tlsTwoWay.bind({address: '192.168.xxx.xxx', port: 8080, family: 1}, err => { tlsTwoWay.bind({ address: '192.168.xxx.xxx', port: 8080, family: 1 }, err => {
if (err) { if (err) {
console.log('bind fail'); console.log('bind fail');
return; return;
...@@ -2012,7 +2236,7 @@ tlsTwoWay.connect(options).then(data => { ...@@ -2012,7 +2236,7 @@ tlsTwoWay.connect(options).then(data => {
}); });
let tlsOneWay = socket.constructTLSSocketInstance(); // One way authentication let tlsOneWay = socket.constructTLSSocketInstance(); // One way authentication
tlsOneWay.bind({address: '192.168.xxx.xxx', port: 8080, family: 1}, err => { tlsOneWay.bind({ address: '192.168.xxx.xxx', port: 8080, family: 1 }, err => {
if (err) { if (err) {
console.log('bind fail'); console.log('bind fail');
return; return;
...@@ -2572,7 +2796,7 @@ Closes a TLSSocket connection. This API uses a promise to return the result. ...@@ -2572,7 +2796,7 @@ Closes a TLSSocket connection. This API uses a promise to return the result.
```js ```js
tls.close().then(() => { tls.close().then(() => {
console.log("close success"); console.log("close success");
}).catch(err => { }).catch((err) => {
console.error(err); console.error(err);
}); });
``` ```
......
...@@ -74,6 +74,7 @@ ...@@ -74,6 +74,7 @@
- [Plug-in Management](subsys-boot-init-plugin.md) - [Plug-in Management](subsys-boot-init-plugin.md)
- [Component-based Startup](subsys-boot-init-sub-unit.md) - [Component-based Startup](subsys-boot-init-sub-unit.md)
- [init Run Log Standardization](subsys-boot-init-log.md) - [init Run Log Standardization](subsys-boot-init-log.md)
- [Seccomp Policy Development](subsys-boot-init-seccomp.md)
- [appspawn Module](subsys-boot-appspawn.md) - [appspawn Module](subsys-boot-appspawn.md)
- [bootstrap Module](subsys-boot-bootstrap.md) - [bootstrap Module](subsys-boot-bootstrap.md)
- [FAQs](subsys-boot-faqs.md) - [FAQs](subsys-boot-faqs.md)
......
# Seccomp Policy Development
## Overview
### Introduction
Secure computing mode (Seccomp) is a security mechanism provided by the Linux kernel. In the Linux system, a large number of system calls can be opened to user-mode programs without any restrictions. However, not all of these system calls are necessarily needed for user-mode programs. In this case, abuse of system calls can lead to system threats. For example, if a process has a security vulnerability, an attacker can run a shellcode segment to trigger system calls that are not triggered during normal execution, resulting in privilege escalation or private information leakage. To prevent such security risks, Seccomp limits the scope of system calls that can be used by programs, so as to reduce system exposure and improve security.
### Operating Mechanism
- Basic mechanism
Seccomp policies exist in the form of policy files. During compilation and building, a policy file is parsed to generate a source file that contains the BPF instruction policies, and then the source file is compiled into a dynamic policy library. During startup of a user-mode process, Seccomp system calls are invoked to load the BPF instruction policies into the kernel through the dynamic policy library.
- Basic features
- A child process inherits the Seccomp policies of its parent process.
- After a Seccomp policy is loaded to the kernel during process running, the policy exists in the memory as a singly linked list and cannot be modified.
- Seccomp policies can be set for a process for multiple times. When a process executes a system call, the kernel traverses the policies specified for the nodes in the singly linked list, and then compares the policies to obtain the policy with the highest priority.
### Constraints
- System restrictions
The system used must be a standard system, and the options listed below must be enabled in the kernel. You can find the kernel option configuration file of the product in **//kernel/linux/config/{linux_version}/arch/{target_cpu}/configs/**.
```shell
CONFIG_HAVE_ARCH_SECCOMP=y
CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
CONFIG_SECCOMP=y
CONFIG_SECCOMP_FILTER=y
```
- Feature restrictions
- The Seccomp policy for non-privileged processes complies with the baseline blocklist mechanism.
- If a process needs to use system calls in the baseline blocklist, the system calls must be declared in the privileged process policy file.
- The same Seccomp policy is enabled for all application processes.
- The same Seccomp policy is enabled for most of system service processes.
- Personalized Seccomp policies can be enabled for the native service processes incubated by the init process.
## Enabling Seccomp
### When to Use
To meet product security requirements, you can enable Seccomp to limit the scope of system calls that can be invoked by processes. The development procedure below describes how to enable the basic functions and policies of Seccomp. Note that the basic functions must meet the feature restrictions described in [Constraints](#constraints). For details about the basic policy file, see [Policy File Overview](#policy-file-overview).
### How to Develop
1. Add the following field to **vendor/Product vendor/Product name/config.json**:
```c
"build_seccomp": true
```
The following is an example of adding the **build_seccomp** field to the product configuration file:
```c
{
"product_name": "MyProduct",
"version": "3.0",
"type": "standard",
"target_cpu": "arm",
"ohos_version": "OpenHarmony 1.0",
"device_company": "MyProductVendor",
"board": "MySOC",
"enable_ramdisk": true,
"build_seccomp": true
"subsystems": [
{
"subsystem": "ace",
"components": [
{ "component": "ace_engine_lite","features":[""] }
]
},
...
]
}
```
2. Perform a full build on the product code to generate an image.
```
./build.sh --product-name *product name* --ccache --build-target make_all --target-cpu *specified CPU*
```
3. Burn the image into the device.
### Debugging and Verification
Check whether Seccomp is enabled for application processes and system service processes.
1. Run the shell command to obtain the process ID (that is, **target pid**) of the target process.
```
ps -ef | grep xxx
```
Information similar to the following is displayed, in which **target pid** is **1686**:
```
media 1686 1 0 08:16:12 ? 00:00:00 xxx
root 1869 1678 4 10:32:29 pts/0 00:00:00 grep xxx
```
2. Check the process status to determine whether Seccomp is enabled.
```shell
cat /proc/[target pid]/status | grep Seccomp
```
Information similar to the following is displayed:
```
Seccomp: 2
Seccomp_filters: 1
```
**Table 1** Description of the Seccomp status
| Parameter | Description |
| --- | --- |
| Seccomp | Whether Seccomp is enabled.<br>- **0**: disabled.<br>- **1**: enabled with the strict mode. Only the read, write, exit, and sigreturn system calls are allowed.<br>- **2**: enabled with the filter mode. The customized policies can be enabled by loading BPF instruction sets. |
| Seccomp_filters | Number of Seccomp policies set for a process. |
## Customizing Seccomp Policies for a Process
### When to Use
If the basic Seccomp policy has been enabled for a product, you can customize Seccomp policies for native service processes incubated by the init process to adapt to diversified security requirements. In this case, the Seccomp policies of other native service processes remain unchanged.
### How to Develop
1. Collect statistics on the system calls required by the 32-bit and 64-bit systems by using the static analysis and Strace statistics methods described in [System Call Statistic Methods](#system-call-statistic-methods). In this way, you will obtain the initial Seccomp policy.
2. Write a policy file. For details, see [How to Write a Common Policy File](#how-to-write-a-common-policy-file).
3. Write and build the **BUILD.gn** file.
1. Store the policy file in the code repository of the service subsystem and create a **BUILD.gn** file. For example, create the **seccomp_policy** folder in the service code repository, and create the policy file and **BUILD.gn** file in the folder.
```shell
//path/to/code/seccomp_policy
├── BUILD.gn
└── example.seccomp.policy
```
2. To parse the policy file and build the policy dynamic library, use the **ohos_prebuilt_seccomp** template to declare the Seccomp policy file path of the process in the **BUILD.gn** file. The **ohos_prebuilt_seccomp** template is defined in the **//base/startup/init/services/modules/seccomp/scripts/seccomp_policy_fixer.gni** file. The following table describes the parameters in the template.
**Table 2** Parameters in the ohos_prebuilt_seccomp template
| Parameter | Description |
| --- | --- |
| sources | Path of the policy configuration file, mandatory. |
| filtername | Filter name, mandatory. The value must be the same as the value of **Services name** in the [boot configuration file](subsys-boot-init-cfg.md) of the process. Otherwise, the attempt to enable Seccomp will fail. This parameter determines the name of the dynamic policy library generated after the build. For example, if **filtername** is set to **xxx**, the name of the dynamic policy library is **libxxx_filter.z.so**. |
| process_type | Process type, mandatory. If the process is one incubated by the init process, set this parameter to **system**; if the process is an application process, set this parameter to **app**.|
| part_name | Part name, mandatory. |
| subsystem_name | Subsystem name, mandatory. |
| install_enable | Option specifying whether to install the policy file to the image, mandatory. Set the value to **true**. |
| install_images | Installation location in the image, mandatory. |
For example:
```python
#Import the template file.
import("//base/startup/init/services/modules/seccomp/scripts/seccomp_policy_fixer.gni")
#Use the ohos_prebuilt_seccomp template.
ohos_prebuilt_seccomp("xxxx_seccomp_filter") {
sources = [ "xxxx.seccomp.policy" ]
filtername = "xxx"
process_type = "system"
part_name = "xx_part_name"
subsystem_name = "x_subsystem_name"
install_enable = true
install_images = [ "xxxxx" ]
}
```
3. Add the build target of **xxxx_seccomp_filter** to other **BUILD.gn** files.
```python
if (build_seccomp) {
deps += [ "path:xxxx_seccomp_filter" ]
}
```
4. Build the dynamic policy library **libxxx_filter.z.so**.
```shell
./build.sh --product-name *product name* --ccache --build-target xxxx_seccomp_filter --target-cpu *specified CPU*
```
If an error message that contains the following information is reported, the process needs to use the system calls in the baseline blocklist. In such a case, you need to declare the corresponding system call in **privileged_process.seccomp.policy**. For details, see [How to Write a Privileged Process Policy File](#how-to-write-a-privileged-process-policy-file). After the declaration is done, try again until the build is successful.
```shell
xx of allow list is in block list
```
5. Use the hdc tool to push the dynamic policy library to the device and restart the device.
```shell
# Push an appropriate library path based on the installation location in the image. For example, if the image is **system** and the system architecture is 32-bit, the path of the dynamic policy library is **/system/lib/seccomp/**.
hdc shell mount -rw -o remount /
hdc file send /path/to/libxxx_filter.z.so /path/to/lib(or lib64)/seccomp/
hdc shell reboot
```
6. Use the [audit statistics](#audit-statistics) method to check and supplement the Seccomp policies. Repeat steps 4 to 6 until the process can run properly.
### Debugging and Verification
1. If Seccomp is not enabled for the target process, [check the Seccomp status](#debugging-and-verification) of the target process.
2. If the process is terminated and audit log information is present in the kernel logs, the Seccomp policy is enabled but the policy list is incomplete. You can find an example audit log in [Audit Statistics](#audit-statistics).
3. If the process is not terminated, comment out the system calls (for example, **setuid**) related to the specified uid in the Seccomp policy file. Rebuild the dynamic policy library, push the library to the image, and restart the process. Then, check whether the process is terminated by Seccomp. If the process is terminated, Seccomp has been enabled.
## FAQs
### How do I determine whether a process termination is caused by Seccomp?
**Symptom**
If a process is terminated under certain conditions, how do I determine whether the issue is caused by Seccomp?
**Solution**
Use either of the following methods:
- Check the crash stack backtrace log of the process. If the signal in the log is **SIGSYS**, the process termination is caused by the Seccomp mechanism. To view the crash stack backtrace content, run the following shell command:
```shell
cat /data/log/faultlog/faultlogger/crash stack backtrace log
```
Example output:
```shell
Generated by HiviewDFX@OpenHarmony
================================================================
Device info:xxx
Build info:xxx
Module name:xxx
Pid:xxxx
Uid:xxxxx
Reason:Signal:SIGSYS(UNKNOWN)
...
```
- Check whether the process is still terminated after Seccomp is disabled. If the process runs properly after Seccomp is disabled, the process termination is caused by Seccomp.
Seccomp is enabled by default. When the device operation mode is set to **root**, you can run the shell command to set the corresponding system parameter to disable Seccomp of the entire system.
```shell
# Set the system parameter to disable Seccomp and restart the process.
param set persist.init.debug.seccomp.enable 0; reboot
# Set the system parameter to enable Seccomp and restart the process.
param set persist.init.debug.seccomp.enable 1; reboot
```
## Reference
### Seccomp source code directory
```
base/startup/init/services/modules/seccomp
├── BUILD.gn
├── gen_syscall_name_nrs.c
├── scripts
│ ├── generate_code_from_policy.py # Policy file parsing script
│ ├── seccomp_policy_fixer.gni # Template definition in the BUILD.gn file for generating the dynamic policy library
│ └── tools # Scripts for collecting system call statistics
├── seccomp_policy # Basic policy files
│ ├── app.blocklist.seccomp.policy
│ ├── app.seccomp.policy
│ ├── privileged_process.seccomp.policy
│ ├── renderer.seccomp.policy
│ ├── spawn.seccomp.policy
│ ├── system.blocklist.seccomp.policy
│ └── system.seccomp.policy
├── seccomp_policy.c # Core Seccomp implementation code
└── seccomp_policy_static.c # Seccomp plug-in code
```
### Policy File Overview
- Location
Basic policy files are stored in **//base/startup/init/services/modules/seccomp/seccomp_policy**.
- Basic policy files
**Table 3** Description of policy files
| Policy File | Description |
| --- | --- |
| system.seccomp.policy | Seccomp policy enabled for most of system service processes.|
| system.blocklist.seccomp.policy | System call baseline blocklist for system processes, that is, the list of system calls that cannot be invoked by non-privileged processes.|
| app.seccomp.policy | Seccomp policy enabled for all application processes.|
| app.blocklist.seccomp.policy | System call baseline blocklist for application processes, that is, the list of system calls that cannot be invoked by application processes.|
| spawn.seccomp.policy | Seccomp policy enabled for the appspawn and nwebspawn processes.|
| renderer.seccomp.policy | Seccomp policy enabled for the rendering processes incubated by the nwebspawn process.|
| privileged_process.seccomp.policy | Privileged process policy file. If certain processes need to use the system calls on the baseline blocklist, you need to declare the corresponding process identifiers and baseline blocklists in this file.|
### How to Write a Common Policy File
- To declare a configuration item, write **@** followed by the configuration item, for example, **@returnValue**.
- Add the content of a configuration item from the next line of this configuration item to the beginning of the next configuration item.
- To comment out a line, add a pound sign (#) at the beginning of this line.
- Set the system architecture to **arm** or **arm64**. Only these two system architectures are supported currently.
- Separate system calls from the system architecture by a semicolon (;). The value **all** indicates that the system calls will be used by all supported system architectures.
- Set other parameters as needed. Except **returnValue**, all the other parameters are optional.
**Table 4** Configuration items in the policy file
| Item | Description | Configuration Rule |
| --- | --- | -- |
| returnValue | Return value. | This parameter is mandatory. Value range:<br>- **LOG**: tolerant mode, in which only audit logs are recorded and the process is not terminated.<br>- **TRAP**: a mode in which the process is terminated and can be passed on to the faultloggerd process.<br>- **KILL_PROCESS**: a mode in which the process is terminated.<br>- **KILL_THREAD**: a mode in which the thread is terminated. |
| headFiles | Header file, which is used to declare the macros in the **allowListWithArgs** and **priorityWithArgs** parameters.| Use **""** and **<>** to include the file name, for example, **<abc.h>** and **"cde.h"**. The default header files are **<linux/filter.h>**, **<stddef.h>**, **<linux/seccomp.h>**, and **<audit.h>**. |
| priority | Allowlist of frequently used system calls. | System calls on the list are treated with a higher priority to improve the performance. |
| priorityWithArgs | Allowlist of frequently used system calls with arguments. | System calls on the list are treated with a higher priority to improve the performance. |
| allowList | Allowlist | List of system calls that can be invoked by a process. |
| allowListWithArgs | List of system calls with arguments that can be invoked by a process. | Separate the system call name and argument by a colon (:). Supported relational operators include **<**, **<=**, **>**, **>=**, **==**, **!=**, and **&**, and supported logical operators include **&&** and \.|\|.<br>Use **arg***n* to specify the SN of the argument in the system. The value of **n** ranges from **0** to **5**. A judgment statement starts with **if** and ends with **else**. Declare the return value after the statement ends, and use a semicolon (;) to separate the judgment statement from the return value.<br>The return value must be in the format of **return xxx**, where the value range of **xxx** is the same as that of **returnValue**. If there are multiple conditions in the judgment statement, separate them with **elif**.|
| blockList | Blocklist of system calls. | Before generating BPF instructions during policy file parsing, the system checks whether the system calls on the allowlist exist in the blocklist. If yes, a parsing error occurs.|
| selfDefineSyscall | Customized system call. | Set the value of this parameter to a number. |
Example: example.seccomp.policy
```
@returnValue
TRAP
@headFiles
"time.h"
@priority
ioctl;all
@allowList
openat;all
close;all
lseek;all
read;all
write;all
setresuid;arm64
setresgid;arm64
setresuid32;arm
setresgid32;arm
@allowListWithArgs
clock_getres:if arg0 >= CLOCK_REALTIME && arg0 <= CLOCK_BOOTTIME; return ALLOW; else return TRAP;all
@blockList
swapon;all
@selfDefineSyscall
787
```
### How to Write a Privileged Process Policy File
- To declare a configuration item, write **@** followed by the configuration item, for example, **@allowBlockList**.
- Add the content of a configuration item from the next line of this configuration item to the beginning of the next configuration item.
- To comment out a line, add a pound sign (#) at the beginning of this line.
- Set the system architecture to **arm** or **arm64**. Only these two system architectures are supported currently.
- Separate system calls from the system architecture by a semicolon (;). The value **all** indicates that the system calls will be used by all supported system architectures.
**Table 5** Configuration items in the privileged process policy file
| Item | Description | Configuration Rule |
| --- | --- | -- |
| privilegedProcessName | Process name identifier. | Character string corresponding to **name** in the **services** parameter in the boot file of the native service process.|
| allowBlockList | Available baseline blocklist. | Fill in the system call and the system architecture.|
The following example shows how to enable process1 and process2 to use the swapon system call in the baseline blocklist.
```
@privilegedProcessName
process1
@allowBlockList
swapon;all
@privilegedProcessName
process2
@allowBlockList
swapon;all
```
### System Call Statistic Methods
**Table 6** Comparison of statistic methods
| Statistic Method | Description | Advantage | Disadvantage |
| --- | --- | --- | --- |
| <div style="width: 50pt">Static analysis | <div style="width: 300pt">Analyze the ELF disassembly code to obtain the call relationship, collect statistics on the APIs that call the libc library, and then parse the LibC library to obtain the call relationship between the LibC APIs and the system call numbers. In this way, you will obtain the system call numbers used by the ELF file.| <div style="width: 100pt">Statistics collection is supported for system calls in abnormal branches. | <div style="width: 100pt">Parsing of call relationship is not supported for pointer functions. |
| Strace statistics | Use Strace to trace service processes or test processes when the device is running. During the trace, the invoked system calls are recorded into logs. Collect the logs after the trace is complete, and use a script to parse the logs and generate a Seccomp policy file.| Easy to use. | System calls can be completely collected only when all code branches are traversed. |
| Audit statistics | After the Seccomp policy is enabled for a process, Seccomp intercepts invalid system calls and records audit log information containing the system call numbers into kernel logs. Collect the logs after the trace is complete, and use a script to parse the logs and generate a Seccomp policy file.| This method can be used as a supplement to the preceding methods. | Logs may be lost.<br>System calls can be completely collected only when all code branches are traversed. |
> **Disclaimer: Using Third-Party Software or Websites**
>
> We may recommend software, information, products, or websites owned or operated by third parties. Such recommendations are usually provided via hyperlinks or other methods to help you access third-party resources.<br>
> We strive to direct you to useful and trusted resources, but it is beyond our reach to guarantee the software, information, products, or services provided by or at third-party resources, or to track changes in these resources. Therefore, we are unable to assume the responsibility for the compliance, accuracy, and completeness of the content or results of any third-party resources, nor for any loss or damage caused by the use or failure of products or services provided by third-party resources.
#### Static Analysis
1. Prepare the environment.
1. Prepare a Linux environment.
2. Download the cross compilers arm-linux-musleabi and aarch64-linux-musl.
```shell
# Add the tool execution path to the environment variable.
export PATH=$PATH:/path/to/arm-linux-musleabi-cross/bin
export PATH=$PATH:/path/to/aarch64-linux-musl-cross/bin
```
3. Download the OpenHarmony source code.
For details, see [Obtaining Source Code](../get-code/sourcecode-acquire.md).
2. Compile **seccomp_filter** to obtain the dependency files **libsyscall_to_nr_arm** and **libsyscall_to_nr_arm64**.
**seccomp_filter** is declared in **base/startup/init/services/modules/seccomp/BUILD.gn** and is used to build the basic dynamic policy library of Seccomp. After the compilation is complete, dependency files are generated in **//out/Product name /gen/base/startup/init/services/modules/seccomp/gen_system_filter/**.
```shell
./build.sh --product-name *product name* --ccache --build-target seccomp_filter --target-cpu *specified CPU*
# Copy the dependency files to the tool folder for later use.
cp out/*product name* /gen/base/startup/init/services/modules/seccomp/gen_system_filter/libsyscall_to_nr_arm* base/startup/init/services/modules/seccomp/scripts/tools/
```
3. Copy the **generate_code_from_policy.py** script file to the tool folder. This script is available at **//base/startup/init/services/modules/seccomp/scripts/**.
```shell
# Go to the root directory of the OpenHarmony source code.
cd /root/to/OpenharmonyCode;
# Go to the directory where the **generate_code_from_policy.py** script file is located.
cd base/startup/init/services/modules/seccomp/scripts/;
# Copy the **generate_code_from_policy.py** script file.
cp generate_code_from_policy.py tools/;
```
4. Compile ELF files related to the service code. In the 32-bit architecture, the implementation of disassembly code redirection for ELF files is complex. Therefore, ELF files are all compiled into 64-bit ELF files to parse the function call relationship.
```shell
./build.sh --product-name *product file* --ccache --target-cpu arm64 --build-target *target file*
```
5. Modify the **collect_elf_syscall.py** script file, and change the paths of the objdump and readelf tools to their absolute paths in the Linux environment. The tools are stored in **//prebuilts**, and more particularly, **//prebuilts/clang/ohos/linux-x86_64/15.0.4/llvm/bin**.
```python
#modified the path of objdump and readelf path
def get_obj_dump_path():
obj_dump_path = '/path/to/prebuilts/clang/ohos/linux-x86_64/15.0.4/llvm/bin/llvm-objdump'
return obj_dump_path
def get_read_elf_path():
read_elf_path = '/path/to/prebuilts/clang/ohos/linux-x86_64/15.0.4/llvm/bin/llvm-readelf'
return read_elf_path
```
6. Use the **collect_elf_syscall.py** script file to parse and generate the corresponding policy file **xxx.seccomp.policy**.
The script file is available at **//base/startup/init/services/modules/seccomp/scripts/tools/**.
**Table 7** Parameters in the collect_elf_syscall.py script file
| Parameter | Description |
| --- | --- |
| --src-elf-path | Folder where the ELF file is located, for example, **~/ohcode/out/rk3568**. Do not end the value with a slash (/).|
| --elf-name| ELF file name, for example, **libmedia_service.z.so**.|
| --src-syscall-path | **libsyscall_to_nr_arm** or **libsyscall_to_nr_arm64**, which corresponds to the architecture specified by **--target-cpu**. |
| --target-cpu | CPU architecture, that is, the architecture for which system calls are collected. This parameter determines the architecture for libC file parsing. Its value can be **arm** or **arm64**. |
| --filter-name | Name of the generated policy file. For example, if the input value is **test**, the generated file name is **test.seccomp.policy**. |
Use **collect_elf_syscall.py** to parse ELF files.
```
# The following example considers **rk3568** as the product and **libmedia_service.z.so** as the ELF file.
python3 collect_elf_syscall.py --src-elf-path ~/ohcode/out/rk3568 --elf-name libmedia_service.z.so --src-syscall-path libsyscall_to_nr_arm64 --target-cpu arm64 --filter-name media_service
```
Example result of xxx.seccomp.policy
```
@allowList
getcwd;arm64
eventfd2;arm64
epoll_create1;arm64
epoll_ctl;arm64
dup;arm64
dup3;arm64
fcntl;arm64
ioctl;arm64
...
```
#### Strace Statistics
1. Use the cross compilers arm-linux-musleabi and aarch64-linux-musl to build the Strace tool for the 32-bit and 64-bit architectures, respectively.
2. [Trace the test process](#tracing-the-test-process) to obtain Strace logs.
3. [Trace the service process](#tracing-the-service-process) to obtain the Strace logs.
4. [Parse Strace logs](#parsing-strace-logs) by using scripts to obtain the Seccomp policy file.
##### Tracing the Test Process
1. Push the Strace tool to the device.
```shell
hdc shell mount -rw -o remount /
hdc file send /path/to/strace /system/bin/
hdc shell chmod a+x /system/bin/strace
```
2. Modify the local embedded code in the [developer test framework](https://gitee.com/openharmony/testfwk_developer_test) so that Strace is executed in the test suite to trace the test process.
Modify the **_init_gtest** and **_run_gtest** functions in **src/core/driver/drivers.py** as follows. If a line starts with a plus sign (+), the line is added; if a line starts with a hyphen (-), the line is deleted.
```python
--- a/src/core/driver/drivers.py
+++ b/src/core/driver/drivers.py
@@ -500,6 +500,8 @@ class CppTestDriver(IDriver):
"rm -rf %s" % self.config.target_test_path)
self.config.device.execute_shell_command(
"mkdir -p %s" % self.config.target_test_path)
+ self.config.device.execute_shell_command(
+ "mkdir -p /data/strace")
self.config.device.execute_shell_command(
"mount -o rw,remount,rw /")
if "fuzztest" == self.config.testtype[0]:
@@ -539,10 +541,11 @@ class CppTestDriver(IDriver):
test_para,
seed)
else:
- command = "cd %s; rm -rf %s.xml; chmod +x *; ./%s %s" % (
+ command = "cd %s; rm -rf %s.xml; chmod +x *; strace -ff -o /data/strace/%s.strace.log ./%s %s" % (
self.config.target_test_path,
filename,
filename,
+ filename,
test_para)
else:
coverage_outpath = self.config.coverage_outpath
```
3. Execute related service test cases.
4. Obtain Strace logs from **/data/strace** on the device.
```shell
hdc file recv /data/strace /path/to/base/startup/init/services/modules/seccomp/scripts/tools/
```
##### Tracing the Service Process
1. Modify the embedded code in the init repository. Specifically, add the following content to **//base/startup/init/services/init/init_common_service.c** before executing the **SetSystemseccompPolicy** function to set the Seccomp policy. If the line starts with a plus sign (+), the line is added; if the line starts with a hyphen (-), the line is deleted. **xxxx** must be the same as the value of **Services name** in the [boot configuration file](subsys-boot-init-cfg.md) of the process.
```c
--- a/services/init/init_common_service.c
+++ b/services/init/init_common_service.c
@@ -155,7 +155,19 @@ static int SetPerms(const Service *service)
// set seccomp policy before setuid
INIT_ERROR_CHECK(SetSystemseccompPolicy(service) == SERVICE_SUCCESS, return SERVICE_FAILURE,
"set seccomp policy failed for service %s", service->name);
-
+ if (strncmp(service->name, "xxxx", strlen("xxxx")) == 0) {
+ pid_t pid = getpid();
+ pid_t pid_child = fork();
+ if (pid_child == 0) {
+ char pidStr[9] = {0};
+ sprintf_s(pidStr, 6, "%d", pid);
+ if (execl("/system/bin/strace", "/system/bin/strace", "-p", (const char *)pidStr, "-ff", "-o", "/data/strace/xxxx.strace.log", NULL) !=0 ) {
+ INIT_LOGE("strace failed");
+ }
+ }
+ sleep(5);
+ }
if (service->servPerm.uID != 0) {
if (setuid(service->servPerm.uID) != 0) {
INIT_LOGE("setuid of service: %s failed, uid = %d", service->name, service->servPerm.uID);
```
2. Perform a full build, and burn the image.
3. Disable SElinux, and push Strace to the device.
```shell
hdc shell setenforce 0
hdc shell mount -rw -o remount /
hdc file send /path/to/strace /system/bin/
hdc shell chmod a+x /system/bin/strace
```
4. Create a folder for storing Strace logs.
```shell
hdc shell mkdir -p /data/strace
```
5. Terminate the service process, and restart it. In the following command, **xxx** indicates the service process name.
```shell
kill -9 $(pidof xxx)
```
6. Perform service operations on the device. Make sure that all code is covered.
7. Obtain Strace logs from **/data/strace** on the device, and save them to the directory where the parsing script is located.
```shell
hdc file recv /data/strace /path/to/base/startup/init/services/modules/seccomp/scripts/tools/
```
##### Parsing Strace Logs
1. Copy the dependency files to the Strace log folder for later use. The dependency files are those generated in step 2 in [Static Analysis](#static-analysis).
```shell
cp out/*product name* /gen/base/startup/init/services/modules/seccomp/gen_system_filter/libsyscall_to_nr_arm* base/startup/init/services/modules/seccomp/scripts/tools/strace/
```
2. Use the **strace_log_analysis.py** script file to parse and generate the corresponding policy file **xxx.seccomp.policy**.
The script file is available at **//base/startup/init/services/modules/seccomp/scripts/tools/**.
**Table 8** Parameters in the strace_log_analysis.py script file
| Parameter | Description |
| --- | --- |
| --src-path | Folder for storing log files. It must contain **libsyscall_to_nr_arm** and **libsyscall_to_nr_arm64**. The folder name must not end with a slash (/), for example, **./strace**.|
| --target-cpu | CPU architecture, which is the same as that of the traced process. Its value can be **arm** or **arm64**. |
| --filter-name | Name of the generated policy file. For example, if the input value is **test**, the generated file name is **test.seccomp.policy**. |
Use the **strace_log_analysis.py** script file to parse Strace logs.
```shell
cd base/startup/init/services/modules/seccomp/scripts/tools;
python3 strace_log_analysis.py --src-path strace --target-cpu *specified CPU* --filter-name xxx
```
Example result of xxx.seccomp.policy
```
@allowList
getcwd;arm64
eventfd2;arm64
epoll_create1;arm64
epoll_ctl;arm64
dup;arm64
dup3;arm64
fcntl;arm64
ioctl;arm64
...
```
#### Audit Statistics
1. Enable the initial Seccomp policy. For details, see [Customizing Seccomp Policies for a Process](#customizing-seccomp-policies-for-a-process).
2. Obtain logs.
1. Create a folder for storing logs.
```shell
mkdir -p /data/audit
```
2. Obtain Seccomp-related audit log information from kernel logs. The logs end with **.audit.log**.
```shell
cat /proc/kmsg | grep type=1326 > /data/audit/media_service.audit.log
```
3. Perform service-related operations and segment fault triggering operations.
1. To trigger a segment fault, add the following code to the service code to call **TriggerSegmentFault** at a certain point to rebuild and burn the image:
```c
static void TriggerSegmentFault(void)
{
pid_t pid_child = fork();
if (pid_child == 0) {
char *test = (char *)0x1234;
*test = 1;
}
}
```
2. After the device is started, run the following shell command to temporarily shut down SELinux and terminate the service process. The process then automatically restarts.
```shell
setenforce 0
```
4. Run the hdc command to obtain audit logs from the **/data/audit** on of the device, and save them to the directory where the parsing script is located.
```shell
hdc file recv /data/audit /path/to/base/startup/init/services/modules/seccomp/scripts/tools/
```
5. Parse the audit logs.
Example audit log:
```shell
<5>[ 198.963101] audit: type=1326 audit(1659528178.748:27): auid=4294967295 uid=0 gid=1000 ses=4294967295 subj=u:r:appspawn:s0 pid=2704 comm="config_dialog_s" exe="/system/bin/appspawn" sig=31 arch=40000028 syscall=
208 compat=1 ip=0xf7b79400 code=0x80000000
```
**Table 9** Key parameters in audit logs
| Parameter | Description |
| --- | --- |
| type | Type. The value **1326** indicates that the log is of the Seccomp type. |
| sig | Semaphore. The value **31** indicates **SIGSYS**, which is the signal sent to the process when Seccomp interception occurs. |
| arch | Architecture ID. The value **40000028** indicates **arm**, and the value **c00000b7** indicates **arm64**. |
| syscall | System call ID. |
| compat | The value **1** indicates the compatibility mode, that is, the arm64 kernel uses arm system calls. |
1. Copy the dependency files to the log folder for later use. The dependency files are those generated in step 2 in [Static Analysis](#static-analysis).
```shell
cp out/*product name* /gen/base/startup/init/services/modules/seccomp/gen_system_filter/libsyscall_to_nr_arm* base/startup/init/services/modules/seccomp/scripts/tools/audit/
```
2. Run the **audit_log_analysis.py** script to parse logs and generate **xxx.seccomp.policy**. The tool is available at **//base/startup/init/services/modules/seccomp/scripts/tools/**.
**Table 10** Parameters in the audit_log_analysis.py script file
| Parameter | Description |
| --- | --- |
| --src-path | Folder for storing log files. It must contain **libsyscall_to_nr_arm** and **libsyscall_to_nr_arm64**. The folder name must not end with a slash (/), for example, **./audit**.|
| --filter-name | Name of the generated policy file. For example, if the input value is **test**, the generated file name is **test.seccomp.policy**. |
```shell
cd base/startup/init/services/modules/seccomp/scripts/tools
python3 audit_log_analysis.py --src-path audit --filter-name xxx
```
### Combining Multiple Policy Files
During [colltatistics on system calls](#system-call-statistic-methods), multiple policy files may be generated. In these policy files, system calls may be repeated or disordered. To solve these problems, you can combine policy files to sort system calls by arm64/arm and by system call number in ascending order.
**Table 11** Parameters in the merge_policy.py script file
| Parameter | Description |
| --- | --- |
| --src-files | Files to be processed, including **libsyscall_to_nr_arm** and **libsyscall_to_nr_arm64**.|
| --filter-name | Name of the generated policy file. For example, if the input value is **test**, the generated file name is **test.seccomp.policy**. |
1. Copy the dependency files to the log folder for later use.
```shell
cp out/*product name* /gen/base/startup/init/services/modules/seccomp/gen_system_filter/libsyscall_to_nr_arm* base/startup/init/services/modules/seccomp/scripts/tools/
```
2. Run the **merge_policy.py** script to merge **policy1.seccomp.policy** and **policy2.seccomp.policy** into **xxxx.seccomp.policy**.
```shell
python3 merge_policy.py --src-files libsyscall_to_nr_arm --src-files libsyscall_to_nr_arm64 --src-files policy1.seccomp.policy --src-files policy2.seccomp.policy --filter-name xxxx
```
...@@ -427,6 +427,7 @@ ...@@ -427,6 +427,7 @@
- [Plug-in Management](subsystems/subsys-boot-init-plugin.md) - [Plug-in Management](subsystems/subsys-boot-init-plugin.md)
- [omponent-based Startup](subsystems/subsys-boot-init-sub-unit.md) - [omponent-based Startup](subsystems/subsys-boot-init-sub-unit.md)
- [init Run Log Standardization](subsystems/subsys-boot-init-log.md) - [init Run Log Standardization](subsystems/subsys-boot-init-log.md)
- [Seccomp Policy Development](subsystems/subsys-boot-init-seccomp.md)
- [appspawn Module](subsystems/subsys-boot-appspawn.md) - [appspawn Module](subsystems/subsys-boot-appspawn.md)
- [bootstrap Module](subsystems/subsys-boot-bootstrap.md) - [bootstrap Module](subsystems/subsys-boot-bootstrap.md)
- [FAQs](subsystems/subsys-boot-faqs.md) - [FAQs](subsystems/subsys-boot-faqs.md)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册