提交 7a20e234 编写于 作者: Mr-YX's avatar Mr-YX 提交者: Gitee

Merge branch 'master' of gitee.com:openharmony/docs into master

Signed-off-by: Mr-YX's avatarmr-yx <496043997@qq.com>
...@@ -3063,7 +3063,7 @@ audioCapturer.read(bufferSize, true, async(err, buffer) => { ...@@ -3063,7 +3063,7 @@ audioCapturer.read(bufferSize, true, async(err, buffer) => {
if (!err) { if (!err) {
console.log("Success in reading the buffer data"); console.log("Success in reading the buffer data");
} }
}; });
``` ```
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
### When to Use<a name="section213mcpsimp"></a> ### When to Use<a name="section213mcpsimp"></a>
Initializing a modem vendor library means to implement **const HRilOps \*RilInitOps\(const struct HRilReport \*reportOps\)** function in the vendor library. This function is mainly used to: Initializing a modem vendor library means to implement **const HRilOps \*RilInitOps\(const struct HRilReport \*reportOps\)** function in the vendor library. This function is mainly used to:
- Receive function pointers to event callbacks of RIL Adapter. When a service event needs to be reported, the target pointer will be called to report the event to RIL Adapter. - Receive function pointers to event callbacks of RIL Adapter. When a service event needs to be reported, the target pointer will be called to report the event to RIL Adapter.
- Create a thread for reading modem nodes. In this thread, the data reported by the modem is read cyclically and parsed as a specific service event for reporting. - Create a thread for reading modem nodes. In this thread, the data reported by the modem is read cyclically and parsed as a specific service event for reporting.
...@@ -14,29 +14,15 @@ Initializing a modem vendor library means to implement **const HRilOps \*RilIni ...@@ -14,29 +14,15 @@ Initializing a modem vendor library means to implement **const HRilOps \*RilIni
The following table describes the API for initializing a modem vendor library. The following table describes the API for initializing a modem vendor library.
**Table 1** API for initializing a modem vendor library **Table 1** API for initializing a modem vendor library
<a name="table223mcpsimp"></a> | API | Description |
<table><thead align="left"><tr id="row229mcpsimp"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p231mcpsimp"><a name="p231mcpsimp"></a><a name="p231mcpsimp"></a>API</p> | -------- | -------- |
</th> | const&nbsp;HRilOps&nbsp;\*RilInitOps(const&nbsp;struct&nbsp;HRilReport&nbsp;\*&nbsp;reportOps) | Provides an entry for running a modem vendor library.<br>Input parameter:<br>**reportOps**: Specifies the pointer to the event callback function, which is passed by RIL Adapter.<br/>Return result: function pointer of the service request API. |
<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p233mcpsimp"><a name="p233mcpsimp"></a><a name="p233mcpsimp"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row235mcpsimp"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p237mcpsimp"><a name="p237mcpsimp"></a><a name="p237mcpsimp"></a>const HRilOps *RilInitOps(const struct HRilReport * reportOps)</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p239mcpsimp"><a name="p239mcpsimp"></a><a name="p239mcpsimp"></a>Function: Provides an entry for running a modem vendor library.</p>
<p id="p56281836194610"><a name="p56281836194610"></a><a name="p56281836194610"></a>Input parameter:</p>
<p id="p240mcpsimp"><a name="p240mcpsimp"></a><a name="p240mcpsimp"></a><strong id="b164737479278"><a name="b164737479278"></a><a name="b164737479278"></a>reportOps</strong>: Specifies the pointer to the event callback function, which is passed by RIL Adapter.</p>
<p id="p241mcpsimp"><a name="p241mcpsimp"></a><a name="p241mcpsimp"></a>Return result: function pointer of the service request API.</p>
</td>
</tr>
</tbody>
</table>
### How to Develop<a name="section51031144122"></a> ### How to Develop<a name="section51031144122"></a>
1. Set the event callback function pointers passed by RIL Adapter through **RilInitOps**. 1. Set the event callback function pointers passed by RIL Adapter through **RilInitOps**.
``` ```
// Define the callback function pointers of the modem vendor library. // Define the callback function pointers of the modem vendor library.
...@@ -51,7 +37,7 @@ The following table describes the API for initializing a modem vendor library. ...@@ -51,7 +37,7 @@ The following table describes the API for initializing a modem vendor library.
``` ```
1. Create the **g\_reader** main thread to enable message looping. 1. Create the **g\_reader** main thread to enable message looping.
``` ```
pthread_attr_t t; pthread_attr_t t;
...@@ -61,7 +47,7 @@ The following table describes the API for initializing a modem vendor library. ...@@ -61,7 +47,7 @@ The following table describes the API for initializing a modem vendor library.
``` ```
1. In the **g\_eventListeners** thread, use **open\(\)** to open a modem node and then create the **g\_reader** thread to read and process messages reported by the modem. 1. In the **g\_eventListeners** thread, use **open\(\)** to open a modem node and then create the **g\_reader** thread to read and process messages reported by the modem.
``` ```
g_fd = open(g_devicePath, O_RDWR); // Open the device node specified by g_devicePath. g_fd = open(g_devicePath, O_RDWR); // Open the device node specified by g_devicePath.
...@@ -121,7 +107,7 @@ The following table describes the API for initializing a modem vendor library. ...@@ -121,7 +107,7 @@ The following table describes the API for initializing a modem vendor library.
### Debugging and Verification<a name="section5351151517132"></a> ### Debugging and Verification<a name="section5351151517132"></a>
1. Use the [hdc\_std](https://gitee.com/openharmony/docs/blob/master/en/device-dev/subsystems/subsys-toolchain-hdc-guide.md#preparations) tool to connect to a debugging device. Then, run the following command to send the generated **libril\_vendor.z.so** library file to the **/system/lib/** directory of the device. For details about how to integrate a library file, see [Integrating Modem Vendor Libraries](#section590mcpsimp). 1. Use the [hdc\_std](https://gitee.com/openharmony/docs/blob/master/en/device-dev/subsystems/subsys-toolchain-hdc-guide.md#preparations) tool to connect to a debugging device. Then, run the following command to send the generated **libril\_vendor.z.so** library file to the **/system/lib/** directory of the device. For details about how to integrate a library file, see [Integrating Modem Vendor Libraries](#section590mcpsimp).
``` ```
hdc_std file send libril_vendor.z.so /system/lib/ hdc_std file send libril_vendor.z.so /system/lib/
...@@ -134,7 +120,7 @@ The following table describes the API for initializing a modem vendor library. ...@@ -134,7 +120,7 @@ The following table describes the API for initializing a modem vendor library.
hdc_std shell reboot hdc_std shell reboot
``` ```
3. Run the **hdc\_std shell hilog** command to view the debug log, and check whether the **RilInitOps\(\)** function is successfully executed. The following debug log is for reference: 3. Run the **hdc\_std shell hilog** command to view the debug log, and check whether the **RilInitOps\(\)** function is successfully executed. The following debug log is for reference:
``` ```
01-01 05:13:23.071 136 2319 D 00000/RilAdapterInit: [RilAdapterDispatch-(hril_hdf.c:55)] sbuf IPC obtain test success! 01-01 05:13:23.071 136 2319 D 00000/RilAdapterInit: [RilAdapterDispatch-(hril_hdf.c:55)] sbuf IPC obtain test success!
...@@ -153,41 +139,16 @@ After receiving a specific telephony service request, RIL Adapter calls the targ ...@@ -153,41 +139,16 @@ After receiving a specific telephony service request, RIL Adapter calls the targ
The following table describes the APIs for responding to modem service requests, with the dial module as an example. The following table describes the APIs for responding to modem service requests, with the dial module as an example.
**Table 2** APIs for responding to modem service requests **Table 2** APIs for responding to modem service requests
<a name="table303mcpsimp"></a> | API | Description |
<table><thead align="left"><tr id="row309mcpsimp"><th class="cellrowborder" valign="top" width="49.84%" id="mcps1.2.3.1.1"><p id="p311mcpsimp"><a name="p311mcpsimp"></a><a name="p311mcpsimp"></a>API</p> | -------- | -------- |
</th> | void&nbsp;ReqDial(ReqDataInfo&nbsp;\*requestInfo,&nbsp;const&nbsp;void&nbsp;\*data,&nbsp;size_t&nbsp;dataLen); | Processes number dial requests.<br>Input parameters:<br>**requestInfo**: request type<br/>**data**: called number<br/>**dataLen**: data length<br/>Return value: none |
<th class="cellrowborder" valign="top" width="50.160000000000004%" id="mcps1.2.3.1.2"><p id="p313mcpsimp"><a name="p313mcpsimp"></a><a name="p313mcpsimp"></a>Description</p> | void&nbsp;(\*OnCallReport)(struct&nbsp;ReportInfo&nbsp;reportInfo,&nbsp;const&nbsp;void&nbsp;\*data,&nbsp;size_t&nbsp;dataLen); | Reports the execution result of a service request to RIL Adapter.<br>Input parameters:<br>**reportInfo**: request type<br/>**data**: called number<br/>**dataLen**: data length<br/>Return value: none |
</th>
</tr>
</thead>
<tbody><tr id="row315mcpsimp"><td class="cellrowborder" valign="top" width="49.84%" headers="mcps1.2.3.1.1 "><p id="p317mcpsimp"><a name="p317mcpsimp"></a><a name="p317mcpsimp"></a>void ReqDial(ReqDataInfo *requestInfo, const void *data, size_t dataLen);</p>
</td>
<td class="cellrowborder" valign="top" width="50.160000000000004%" headers="mcps1.2.3.1.2 "><p id="p319mcpsimp"><a name="p319mcpsimp"></a><a name="p319mcpsimp"></a>Function: Processes number dial requests.</p>
<p id="p12610151394115"><a name="p12610151394115"></a><a name="p12610151394115"></a>Input parameters:</p>
<a name="ul105511416204116"></a><a name="ul105511416204116"></a><ul id="ul105511416204116"><li><strong id="b85517162414"><a name="b85517162414"></a><a name="b85517162414"></a>requestInfo</strong>: request type</li></ul>
<a name="ul1676502416411"></a><a name="ul1676502416411"></a><ul id="ul1676502416411"><li><strong id="b1576510240416"><a name="b1576510240416"></a><a name="b1576510240416"></a>data</strong>: called number</li></ul>
<a name="ul842034134114"></a><a name="ul842034134114"></a><ul id="ul842034134114"><li><strong id="b1542193411415"><a name="b1542193411415"></a><a name="b1542193411415"></a>dataLen</strong>: data length</li></ul>
<p id="p323mcpsimp"><a name="p323mcpsimp"></a><a name="p323mcpsimp"></a>Return value: none</p>
</td>
</tr>
<tr id="row324mcpsimp"><td class="cellrowborder" valign="top" width="49.84%" headers="mcps1.2.3.1.1 "><p id="p326mcpsimp"><a name="p326mcpsimp"></a><a name="p326mcpsimp"></a>void (*OnCallReport)(struct ReportInfo reportInfo, const void *data, size_t dataLen);</p>
</td>
<td class="cellrowborder" valign="top" width="50.160000000000004%" headers="mcps1.2.3.1.2 "><p id="p328mcpsimp"><a name="p328mcpsimp"></a><a name="p328mcpsimp"></a>Function: Reports the execution result of a service request to RIL Adapter.</p>
<p id="p489264432"><a name="p489264432"></a><a name="p489264432"></a>Input parameters:</p>
<a name="ul44156301444"></a><a name="ul44156301444"></a><ul id="ul44156301444"><li><strong id="b15415930154418"><a name="b15415930154418"></a><a name="b15415930154418"></a>reportInfo</strong>: request type</li></ul>
<a name="ul18380115494513"></a><a name="ul18380115494513"></a><ul id="ul18380115494513"><li><strong id="b83808549457"><a name="b83808549457"></a><a name="b83808549457"></a>data</strong>: called number</li></ul>
<a name="ul118421156184517"></a><a name="ul118421156184517"></a><ul id="ul118421156184517"><li><strong id="b48421056144519"><a name="b48421056144519"></a><a name="b48421056144519"></a>dataLen</strong>: data length</li></ul>
<p id="p332mcpsimp"><a name="p332mcpsimp"></a><a name="p332mcpsimp"></a>Return value: none</p>
</td>
</tr>
</tbody>
</table>
### How to Develop<a name="section17190412101414"></a> ### How to Develop<a name="section17190412101414"></a>
1. Implement processing of dial requests in the **ReqDial\(\)** API. 1. Implement processing of dial requests in the **ReqDial\(\)** API.
``` ```
// Implement the API for processing dial requests. // Implement the API for processing dial requests.
...@@ -226,7 +187,7 @@ The following table describes the APIs for responding to modem service requests, ...@@ -226,7 +187,7 @@ The following table describes the APIs for responding to modem service requests,
} }
``` ```
2. After the modem executes the dial command, report the execution result to RIL Adapter via **OnCallReport\(\)**. 2. After the modem executes the dial command, report the execution result to RIL Adapter via **OnCallReport\(\)**.
``` ```
ret = SendCommandLock(cmd, NULL, 0, &pResponse); ret = SendCommandLock(cmd, NULL, 0, &pResponse);
...@@ -241,7 +202,7 @@ The following table describes the APIs for responding to modem service requests, ...@@ -241,7 +202,7 @@ The following table describes the APIs for responding to modem service requests,
### Debugging and Verification<a name="section10207938171413"></a> ### Debugging and Verification<a name="section10207938171413"></a>
1. Use the [hdc\_std](https://gitee.com/openharmony/docs/blob/master/en/device-dev/subsystems/subsys-toolchain-hdc-guide.md#preparations) tool to connect to a debugging device. Then, run the following command to send the generated **libril\_vendor.z.so** library file to the **/system/lib/** directory of the device. 1. Use the [hdc\_std](https://gitee.com/openharmony/docs/blob/master/en/device-dev/subsystems/subsys-toolchain-hdc-guide.md#preparations) tool to connect to a debugging device. Then, run the following command to send the generated **libril\_vendor.z.so** library file to the **/system/lib/** directory of the device.
``` ```
hdc_std file send libril_vendor.z.so /system/lib/ hdc_std file send libril_vendor.z.so /system/lib/
...@@ -254,7 +215,7 @@ The following table describes the APIs for responding to modem service requests, ...@@ -254,7 +215,7 @@ The following table describes the APIs for responding to modem service requests,
hdc_std shell reboot hdc_std shell reboot
``` ```
3. Run the **hdc\_std shell** command. Then, run the **./system/bin/ril\_adapter\_test** command, type **1**, and enter the phone number as prompted to test the call function. 3. Run the **hdc\_std shell** command. Then, run the **./system/bin/ril\_adapter\_test** command, type **1**, and enter the phone number as prompted to test the call function.
``` ```
hdc_std shell hdc_std shell
...@@ -270,7 +231,7 @@ The following table describes the APIs for responding to modem service requests, ...@@ -270,7 +231,7 @@ The following table describes the APIs for responding to modem service requests,
1 1
``` ```
4. Open another terminal window, and run the **hdc\_std shell hilog** command. Then, view the log to check whether **ReqDial\(\)** is successfully executed. The following debug log is for reference: 4. Open another terminal window, and run the **hdc\_std shell hilog** command. Then, view the log to check whether **ReqDial\(\)** is successfully executed. The following debug log is for reference:
``` ```
01-01 05:27:27.419 136 408 D 02b01/Rilvendor: [SendCommandLock-(at_support.c:210)] SendCommandLock enter, cmd: ATD17620373527 01-01 05:27:27.419 136 408 D 02b01/Rilvendor: [SendCommandLock-(at_support.c:210)] SendCommandLock enter, cmd: ATD17620373527
...@@ -299,30 +260,15 @@ A modem node thread reads the messages reported by the modem cyclically, parses ...@@ -299,30 +260,15 @@ A modem node thread reads the messages reported by the modem cyclically, parses
The following table describes the API for reporting modem events. The following table describes the API for reporting modem events.
**Table 3** API for reporting modem events **Table 3** API for reporting modem events
<a name="table407mcpsimp"></a> | API | Description |
<table><thead align="left"><tr id="row413mcpsimp"><th class="cellrowborder" valign="top" width="52%" id="mcps1.2.3.1.1"><p id="p415mcpsimp"><a name="p415mcpsimp"></a><a name="p415mcpsimp"></a>API</p> | -------- | -------- |
</th> | void&nbsp;OnNotifyOps(const&nbsp;char&nbsp;\*s,&nbsp;const&nbsp;char&nbsp;\*smsPdu) | Distributes the events reported by the modem.<br>Input parameters:<br/>**s**: AT command prefix<br/>**smsPdu**: PDU of the SMS message<br/>Return value: none |
<th class="cellrowborder" valign="top" width="48%" id="mcps1.2.3.1.2"><p id="p417mcpsimp"><a name="p417mcpsimp"></a><a name="p417mcpsimp"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row419mcpsimp"><td class="cellrowborder" valign="top" width="52%" headers="mcps1.2.3.1.1 "><p id="p421mcpsimp"><a name="p421mcpsimp"></a><a name="p421mcpsimp"></a>void OnNotifyOps(const char *s, const char *smsPdu)</p>
</td>
<td class="cellrowborder" valign="top" width="48%" headers="mcps1.2.3.1.2 "><p id="p423mcpsimp"><a name="p423mcpsimp"></a><a name="p423mcpsimp"></a>Function: Distributes the events reported by the modem.</p>
<p id="p17924530141912"><a name="p17924530141912"></a><a name="p17924530141912"></a>Input parameters:</p>
<a name="ul678053915191"></a><a name="ul678053915191"></a><ul id="ul678053915191"><li><strong id="b14780173912196"><a name="b14780173912196"></a><a name="b14780173912196"></a>s</strong>: AT command prefix</li></ul>
<a name="ul206343434192"></a><a name="ul206343434192"></a><ul id="ul206343434192"><li><strong id="b65891958173518"><a name="b65891958173518"></a><a name="b65891958173518"></a>smsPdu</strong>: PDU of the SMS message</li></ul>
<p id="p426mcpsimp"><a name="p426mcpsimp"></a><a name="p426mcpsimp"></a>Return value: none</p>
</td>
</tr>
</tbody>
</table>
### How to Develop<a name="section16394112401512"></a> ### How to Develop<a name="section16394112401512"></a>
1. Call **OnNotifyOps\(\)** in the g\_reader thread of the modem device node to parse reported modem events. On determining the command type, call **OnXxxReport\(\)** to report the parsed module events to the hril layer. 1. Call **OnNotifyOps\(\)** in the g\_reader thread of the modem device node to parse reported modem events. On determining the command type, call **OnXxxReport\(\)** to report the parsed module events to the hril layer.
``` ```
// Parse the data reported by the modem as events proactively reported by the corresponding module. // Parse the data reported by the modem as events proactively reported by the corresponding module.
...@@ -352,7 +298,7 @@ The following table describes the API for reporting modem events. ...@@ -352,7 +298,7 @@ The following table describes the API for reporting modem events.
``` ```
1. Distribute the reported events from the **hril** layer to the Telephony Service layer. 1. Distribute the reported events from the **hril** layer to the Telephony Service layer.
``` ```
// Report the call status proactively. // Report the call status proactively.
...@@ -380,7 +326,7 @@ The following table describes the API for reporting modem events. ...@@ -380,7 +326,7 @@ The following table describes the API for reporting modem events.
### Debugging and Verification<a name="section16999174401516"></a> ### Debugging and Verification<a name="section16999174401516"></a>
1. Use the [hdc\_std](https://gitee.com/openharmony/docs/blob/master/en/device-dev/subsystems/subsys-toolchain-hdc-guide.md#preparations) tool to connect to a debugging device. Then, run the following command to send the generated **libril\_vendor.z.so** library file to the **/system/lib/** directory of the device. 1. Use the [hdc\_std](https://gitee.com/openharmony/docs/blob/master/en/device-dev/subsystems/subsys-toolchain-hdc-guide.md#preparations) tool to connect to a debugging device. Then, run the following command to send the generated **libril\_vendor.z.so** library file to the **/system/lib/** directory of the device.
``` ```
hdc_std file send libril_vendor.z.so /system/lib/ hdc_std file send libril_vendor.z.so /system/lib/
...@@ -393,7 +339,7 @@ The following table describes the API for reporting modem events. ...@@ -393,7 +339,7 @@ The following table describes the API for reporting modem events.
hdc_std shell reboot hdc_std shell reboot
``` ```
3. Run the **hdc\_std shell** command. Then, run the **./system/bin/ril\_adapter\_test** command, type **1**, and enter the phone number as prompted to test the call function. 3. Run the **hdc\_std shell** command. Then, run the **./system/bin/ril\_adapter\_test** command, type **1**, and enter the phone number as prompted to test the call function.
``` ```
hdc_std shell hdc_std shell
...@@ -409,7 +355,7 @@ The following table describes the API for reporting modem events. ...@@ -409,7 +355,7 @@ The following table describes the API for reporting modem events.
1 1
``` ```
4. Open another terminal window, and run the **hdc\_std shell hilog** command. Then, view the log to check whether **OnNotifyOps\(\)** is successfully executed. The following debug log is for reference: 4. Open another terminal window, and run the **hdc\_std shell hilog** command. Then, view the log to check whether **OnNotifyOps\(\)** is successfully executed. The following debug log is for reference:
``` ```
01-01 00:08:01.334 546 551 D 02b01/TelRilTest: [DialResponse-(tel_ril_call.cpp:280)] DialResponse --> radioResponseInfo->serial:2, radioResponseInfo->error:0 01-01 00:08:01.334 546 551 D 02b01/TelRilTest: [DialResponse-(tel_ril_call.cpp:280)] DialResponse --> radioResponseInfo->serial:2, radioResponseInfo->error:0
...@@ -434,16 +380,16 @@ The following table describes the API for reporting modem events. ...@@ -434,16 +380,16 @@ The following table describes the API for reporting modem events.
### Development Examples<a name="section33444350167"></a> ### Development Examples<a name="section33444350167"></a>
- **Outgoing Call** - **Outgoing Call**
The following figure shows the API calling for an outgoing call. The following figure shows the API calling for an outgoing call.
**Figure 1** Time sequence of API calling for an outgoing call<a name="fig494mcpsimp"></a> **Figure 1** Time sequence of API calling for an outgoing call<a name="fig494mcpsimp"></a>
![](figure/en-us_image_0000001171507146.png) ![](figure/en-us_image_0000001171507146.png)
When an application initiates an outgoing call, RIL Adapter receives a call request, and the **hril** layer invokes the **ReqDial\(\)** function. In **ReqDial\(\)**, the data passed by the Telephony Service is encapsulated as an AT command and sent to the modem. After executing the dial command, the modem reports the execution result to RIL Adapter through **OnCallReport\(\)**. When an application initiates an outgoing call, RIL Adapter receives a call request, and the **hril** layer invokes the **ReqDial\(\)** function. In **ReqDial\(\)**, the data passed by the Telephony Service is encapsulated as an AT command and sent to the modem. After executing the dial command, the modem reports the execution result to RIL Adapter through **OnCallReport\(\)**.
``` ```
// Callback function pointer of the call module // Callback function pointer of the call module
...@@ -513,18 +459,18 @@ The following table describes the API for reporting modem events. ...@@ -513,18 +459,18 @@ The following table describes the API for reporting modem events.
``` ```
- **Incoming Call** - **Incoming Call**
The following figure shows the API calling of an incoming call. The following figure shows the API calling of an incoming call.
**Figure 2** Time sequence of API calling for an incoming call<a name="fig556mcpsimp"></a> **Figure 2** Time sequence of API calling for an incoming call<a name="fig556mcpsimp"></a>
![](figure/en-us_image_0000001214727595.png) ![](figure/en-us_image_0000001214727595.png)
The **g\_reader** thread cyclically reads the messages reported by the modem. When the modem receives an incoming call event, it actively reports the information about the incoming call. The **g\_reader** thread cyclically reads the messages reported by the modem. When the modem receives an incoming call event, it actively reports the information about the incoming call.
The **g\_reader** thread calls **OnNotifyOps\(\)** to parse the reported information. If the parsed data reported by the modem starts with characters such as **+CRING** or **RING**, it indicates that an incoming call event exists. In this case, the event is reported to RIL Adapter through **OnCallReport\(reportInfo, NULL, 0\)**. The **g\_reader** thread calls **OnNotifyOps\(\)** to parse the reported information. If the parsed data reported by the modem starts with characters such as **+CRING** or **RING**, it indicates that an incoming call event exists. In this case, the event is reported to RIL Adapter through **OnCallReport\(reportInfo, NULL, 0\)**.
``` ```
// Parse the data reported by the modem as events proactively reported by the corresponding module. // Parse the data reported by the modem as events proactively reported by the corresponding module.
...@@ -558,7 +504,7 @@ The following table describes the API for reporting modem events. ...@@ -558,7 +504,7 @@ The following table describes the API for reporting modem events.
### Configuring Compilation Information<a name="section592mcpsimp"></a> ### Configuring Compilation Information<a name="section592mcpsimp"></a>
Compile the modem vendor library into a dynamic library by using **BUILD.gn**. Upon startup, RIL Adapter loads the dynamic library to the system in dlopen mode and then initializes the library. For details about how to implement vendor library initialization, see [Initializing a Modem Vendor Library](#section211mcpsimp). The following is an example of **BUILD.gn**: Compile the modem vendor library into a dynamic library by using **BUILD.gn**. Upon startup, RIL Adapter loads the dynamic library to the system in dlopen mode and then initializes the library. For details about how to implement vendor library initialization, see [Initializing a Modem Vendor Library](#section211mcpsimp). The following is an example of **BUILD.gn**:
``` ```
import("//build/ohos.gni") import("//build/ohos.gni")
...@@ -588,5 +534,5 @@ ohos_shared_library("ril_vendor") { // Modem vendor library ...@@ -588,5 +534,5 @@ ohos_shared_library("ril_vendor") { // Modem vendor library
### Debugging and Verification<a name="section620mcpsimp"></a> ### Debugging and Verification<a name="section620mcpsimp"></a>
1. Compile the code. 1. Compile the code.
2. Check whether **libril\_vendor.z.so** exists in the **/out/{device_name}/telephony/ril\_adapter** directory. If yes, the integration is successful. Otherwise, correct the error and perform debugging and verification again. 2. Check whether **libril\_vendor.z.so** exists in the **/out/{device_name}/telephony/ril\_adapter** directory. If yes, the integration is successful. Otherwise, correct the error and perform debugging and verification again.
...@@ -2,10 +2,10 @@ ...@@ -2,10 +2,10 @@
## Basic Test Framework Environment ## Basic Test Framework Environment
|Environment|Operating System|Linux Extended Component|Python|Python Plug-ins|NFS Server|HDC| | Environment | Operating System | Linux Extended Component | Python | Python Plug-ins | NFS Server | HDC |
|------------|------------|------------|------------|------------|------------|------------| | ------------ | ------------ | ------------ | ------------ | ------------ | ------------ | ------------ |
|Version|Ubuntu 18.04 or later|libreadline-dev|3.7.5 or later|- pySerial 3.3 or later<br>- Paramiko 2.7.1 or later<br>- Setuptools 40.8.0 or later<br>- rsa4.0 or later|haneWIN NFS Server 1.2.50 or later, or NFS v4 or later| 1.1.0 or later| | Version | Ubuntu 18.04 or later | libreadline-dev | 3.7.5 or later | - pySerial 3.3 or later<br>- Paramiko 2.7.1 or later<br>- Setuptools 40.8.0 or later<br>- rsa4.0 or later | haneWIN NFS Server 1.2.50 or later, or NFS v4 or later | 1.1.0 or later |
|Description|Provides code build environment.|Plug-in used to read commands.|Language used by the test framework.|- pySerial: supports Python serial port communication. <br>- Paramiko: allows Python to use SSH. <br>- Setuptools: allows Python packages to be created and distributed easily. <br>- rsa: implements RSA encryption in Python.|Enables devices to be connected through the serial port.| A tool that enables devices to be connected through the HarmonyOS Device Connector (HDC).| | Description | Provides code build environment. | Plug-in used to read commands. | Language used by the test framework. | - pySerial: supports Python serial port communication. <br>- Paramiko: allows Python to use SSH. <br>- Setuptools: allows Python packages to be created and distributed easily. <br>- rsa: implements RSA encryption in Python. | Enables devices to be connected through the serial port. | A tool that enables devices to be connected through the HarmonyOS Device Connector (HDC). |
## Installation Process ## Installation Process
1. Run the following command to install the Linux extended component libreadline: 1. Run the following command to install the Linux extended component libreadline:
...@@ -68,15 +68,14 @@ ...@@ -68,15 +68,14 @@
nfs-kernel-server is already the newest version (1:1.3.4-2.1ubuntu5.3). nfs-kernel-server is already the newest version (1:1.3.4-2.1ubuntu5.3).
0 upgraded, 0 newly installed, 0 to remove and 11 not upgraded. 0 upgraded, 0 newly installed, 0 to remove and 11 not upgraded.
``` ```
7. Install the HDC tool if the device supports HDC connections. For details about the installation process, see: 7. Install the HDC tool if the device supports HDC connections. For details about the installation process, see [Readme](https://gitee.com/openharmony/developtools_hdc_standard/blob/master/README.md).
https://gitee.com/openharmony/developtools_hdc_standard/blob/master/README.md
## Checking the Environment ## Checking the Environment
| Check Item|Operation|Requirements| | Check Item | Operation | Expected Result |
| --- | --- | --- | | --- | --- | --- |
| Check whether Python is installed successfully.|Run the **python --version** command.|The Python version is 3.7.5 or later.| | Whether Python is successfully installed | Run the **python --version** command. | The Python version is 3.7.5 or later. |
| Check whether Python plug-ins are successfully installed.|Go to the **test/developertest** directory and run **start.bat** or **start.sh**.| The **>>>** prompt is displayed.| | Whether Python plug-ins are successfully installed | Go to the **test/developertest** directory and run **start.bat** or **start.sh**. | The **>>>** prompt is displayed. |
|Check the NFS server status (for the devices that support only serial port output).|Log in to the development board through the serial port and run the **mount** command to mount the NFS.|The file directory can be mounted.| | NFS server status (for the devices that support only serial port output) | Log in to the development board through the serial port and run the **mount** command to mount the NFS. | The file directory can be mounted. |
|Check whether the HDC tool is successfully installed.|Run the **hdc_std -v** command.|The HDC version is 1.1.0 or later.| | Whether HDC tool is successfully installed | Run the **hdc_std -v** command. | The HDC version is 1.1.0 or later. |
...@@ -27,7 +27,15 @@ ...@@ -27,7 +27,15 @@
- 语言:必选,使用2个或3个小写英文字母表示(可参考ISO-639标准),例如英文使用“en”表示,中文使用“zh”表示。 - 语言:必选,使用2个或3个小写英文字母表示(可参考ISO-639标准),例如英文使用“en”表示,中文使用“zh”表示。
- 脚本:可选,使用4个英文字母表示,其中首字母需要大写,后面3个使用小写字母(可参考ISO-15924)。例如,中文繁体使用脚本“Hant”表示,中文简体使用脚本“Hans”表示。 - 脚本:可选,使用4个英文字母表示,其中首字母需要大写,后面3个使用小写字母(可参考ISO-15924)。例如,中文繁体使用脚本“Hant”表示,中文简体使用脚本“Hans”表示。
- 国家或地区:可选,使用两个大写字母表示(可参考ISO-3166),例如中国使用“CN”表示,美国使用“US”表示; - 国家或地区:可选,使用两个大写字母表示(可参考ISO-3166),例如中国使用“CN”表示,美国使用“US”表示;
- 扩展参数:可选,由key和value两部分组成,目前支持以下扩展参数(可参考BCP 47扩展)。各个扩展参数之间没有严格的顺序,使用“-key-value”的格式书写。扩展参数整体使用“-u”连接到语言、脚本、地区后面。例如“zh-u-nu-latn-ca-chinese”表示使用“latn”数字系统,使用“chinese”日历系统、“latn”数字系统。扩展参数也可以通过第二个参数传入。 - 扩展参数:可选,由key和value两部分组成,目前支持以下扩展参数(可参考BCP 47扩展)。各个扩展参数之间没有严格的顺序,使用“-key-value”的格式书写。扩展参数整体使用“-u”连接到语言、脚本、地区后面。例如“zh-u-nu-latn-ca-chinese”表示使用“latn”数字系统,“chinese”日历系统。扩展参数也可以通过第二个参数传入。
| 扩展参数ID | 扩展参数说明 |
| -------- | -------- |
| ca | 表示日历系统 |
| co | 表示排序规则 |
| hc | 表示守时惯例 |
| nu | 表示数字系统 |
| kn | 表示字符串排序、比较时是否考虑数字的实际值 |
| kf | 表示字符串排序、比较时是否考虑大小写 |
| 扩展参数ID | 扩展参数说明 | | 扩展参数ID | 扩展参数说明 |
| -------- | -------- | | -------- | -------- |
......
...@@ -25,6 +25,6 @@ import Want from '@ohos.application.Want'; ...@@ -25,6 +25,6 @@ import Want from '@ohos.application.Want';
| type | 只读 | string | 否 | 表示MIME type类型描述,比如:"text/plain" 、 "image/*"等。 | | type | 只读 | string | 否 | 表示MIME type类型描述,比如:"text/plain" 、 "image/*"等。 |
| flags | 只读 | number | 否 | 表示处理Want的方式。默认传数字,具体参考:[flags说明](js-apis-featureAbility.md#flags说明)。 | | flags | 只读 | number | 否 | 表示处理Want的方式。默认传数字,具体参考:[flags说明](js-apis-featureAbility.md#flags说明)。 |
| action | 只读 | string | 否 | 表示action选项描述。 | | action | 只读 | string | 否 | 表示action选项描述。 |
| parameters | 只读 | {[key: string]: any} | 否 | 表示WantParams描述。 | | parameters | 只读 | {[key: string]: any} | 否 | 表示WantParams描述,由开发者自行决定传入的键值对。默认会携带以下key值:<br>ohos.aafwk.pacallerPid 表示拉起方的pid。<br>ohos.aafwk.param.callerToken 表示拉起方的token。<br>ohos.aafwk.param.callerUid 表示发起方的uid。[Bundle](js-apis-Bundle.js)模块中userId参数,可用于获取应用信息、包信息等,具体参考:[Bundle](js-apis-Bundle.js)。 |
| entities | 只读 | Array\<string> | 否 | 表示entities相关描述。 | | entities | 只读 | Array\<string> | 否 | 表示entities相关描述。 |
| moduleName<sup>9+</sup> | 只读 | string | 否 | 表示待启动的Ability所属的模块(module)。同一应用的不同hap的组件可能重名,仅通过BundleName和AbilityName无法区分时,可以通过设置moduleName加以区分,以匹配到指定的Ability。 | | | moduleName<sup>9+</sup> | 只读 | string | 否 | 表示待启动的Ability所属的模块(module)。同一应用的不同hap的组件可能重名,仅通过BundleName和AbilityName无法区分时,可以通过设置moduleName加以区分,以匹配到指定的Ability。 | |
...@@ -3085,7 +3085,7 @@ audioCapturer.read(bufferSize, true, async(err, buffer) => { ...@@ -3085,7 +3085,7 @@ audioCapturer.read(bufferSize, true, async(err, buffer) => {
if (!err) { if (!err) {
console.log("Success in reading the buffer data"); console.log("Success in reading the buffer data");
} }
}; });
``` ```
......
# Bundle模块(JS端SDK接口) # 默认应用管理
本模块提供查询默认应用的能力,支持查询当前应用是否是默认应用。 本模块提供查询默认应用的能力,支持查询当前应用是否是默认应用。
...@@ -39,7 +39,7 @@ isDefaultApplication(type: string): Promise\<boolean> ...@@ -39,7 +39,7 @@ isDefaultApplication(type: string): Promise\<boolean>
| 名称 | 类型 | 必填 | 描述 | | 名称 | 类型 | 必填 | 描述 |
| ----------- | ------ | ---- | --------------------------------------- | | ----------- | ------ | ---- | --------------------------------------- |
| type | string | 是 | 要查询的默认应用名称,取[ApplicationType](#defaultappmgrapplicationtype)中的值。 | | type | string | 是 | 要查询的应用类型,取[ApplicationType](#defaultappmgrapplicationtype)中的值。 |
**返回值:** **返回值:**
...@@ -70,8 +70,8 @@ isDefaultApplication(type: string, callback: AsyncCallback\<boolean>): void ...@@ -70,8 +70,8 @@ isDefaultApplication(type: string, callback: AsyncCallback\<boolean>): void
| 名称 | 类型 | 必填 | 描述 | | 名称 | 类型 | 必填 | 描述 |
| ----------- | ------------------------------- | ---- | --------------------------------------- | | ----------- | ------------------------------- | ---- | --------------------------------------- |
| type | string | 是 | 要查询的默认应用名称,取[ApplicationType](#defaultappmgrapplicationtype)中的值。 | | type | string | 是 | 要查询的应用类型,取[ApplicationType](#defaultappmgrapplicationtype)中的值。 |
| callback | AsyncCallback<boolean> | 是 | 程序启动作为入参的回调函数,返回当前应用是否是默认应用,true表示是默认应用,false表示不是默认应用。 | | callback | AsyncCallback\<boolean> | 是 | 程序启动作为入参的回调函数,返回当前应用是否是默认应用,true表示是默认应用,false表示不是默认应用。 |
**示例:** **示例:**
......
...@@ -327,7 +327,12 @@ SystemCapability.Ability.Form ...@@ -327,7 +327,12 @@ SystemCapability.Ability.Form
| --------------- | ------------------------------------------------------------ | ---- | ------------------------------------------------------------ | | --------------- | ------------------------------------------------------------ | ---- | ------------------------------------------------------------ |
| want | [Want](js-apis-application-Want.md) | 是 | abilityName: 目标卡片ability<br/>parameters:<br/>"ohos.extra.param.key.form_dimension"<br/>"ohos.extra.param.key.form_name"<br/>"ohos.extra.param.key.module_name" | | want | [Want](js-apis-application-Want.md) | 是 | abilityName: 目标卡片ability<br/>parameters:<br/>"ohos.extra.param.key.form_dimension"<br/>"ohos.extra.param.key.form_name"<br/>"ohos.extra.param.key.module_name" |
| formBindingData | [FormBindingData](js-apis-formbindingdata.md#formbindingdata) | 否 | 用于创建卡片的数据 | | formBindingData | [FormBindingData](js-apis-formbindingdata.md#formbindingdata) | 否 | 用于创建卡片的数据 |
| callback | AsyncCallback&lt;string&gt; | 是 | callback形式返回卡片标识 |
**返回值:**
| 类型 | 说明 |
| :------------ | :---------------------------------- |
| Promise&lt;string&gt; | Promise实例,用于返回卡片标识。 |
**示例:** **示例:**
......
...@@ -115,14 +115,13 @@ getSystemLanguage(): string ...@@ -115,14 +115,13 @@ getSystemLanguage(): string
setSystemLanguage(language: string): boolean setSystemLanguage(language: string): boolean
设置系统语言。 设置系统语言。<br>
该接口为系统接口。
**需要权限**:ohos.permission.UPDATE_CONFIGURATION **需要权限**:ohos.permission.UPDATE_CONFIGURATION
**系统能力**:SystemCapability.Global.I18n **系统能力**:SystemCapability.Global.I18n
**系统API**: 该接口为系统接口,三方应用不支持调用。
**参数:** **参数:**
| 参数名 | 类型 | 说明 | | 参数名 | 类型 | 说明 |
| -------- | ------ | ----- | | -------- | ------ | ----- |
...@@ -209,14 +208,13 @@ getSystemRegion(): string ...@@ -209,14 +208,13 @@ getSystemRegion(): string
setSystemRegion(region: string): boolean setSystemRegion(region: string): boolean
设置系统区域。 设置系统区域。<br>
该接口为系统接口。
**需要权限**:ohos.permission.UPDATE_CONFIGURATION **需要权限**:ohos.permission.UPDATE_CONFIGURATION
**系统能力**:SystemCapability.Global.I18n **系统能力**:SystemCapability.Global.I18n
**系统API**: 该接口为系统接口,三方应用不支持调用。
**参数:** **参数:**
| 参数名 | 类型 | 说明 | | 参数名 | 类型 | 说明 |
| ------ | ------ | ----- | | ------ | ------ | ----- |
...@@ -256,14 +254,13 @@ getSystemLocale(): string ...@@ -256,14 +254,13 @@ getSystemLocale(): string
setSystemLocale(locale: string): boolean setSystemLocale(locale: string): boolean
设置系统Locale。 设置系统Locale。<br>
该接口为系统接口。
**需要权限**:ohos.permission.UPDATE_CONFIGURATION **需要权限**:ohos.permission.UPDATE_CONFIGURATION
**系统能力**:SystemCapability.Global.I18n **系统能力**:SystemCapability.Global.I18n
**系统API**: 该接口为系统接口,三方应用不支持调用。
**参数:** **参数:**
| 参数名 | 类型 | 说明 | | 参数名 | 类型 | 说明 |
| ------ | ------ | --------------- | | ------ | ------ | --------------- |
...@@ -1547,4 +1544,137 @@ getOffset(date?: number): number ...@@ -1547,4 +1544,137 @@ getOffset(date?: number): number
``` ```
var timezone = i18n.getTimeZone(); var timezone = i18n.getTimeZone();
timezone.getOffset(1234567890); timezone.getOffset(1234567890);
```
### getAvailableIDs<sup>9+</sup>
static getAvailableIDs(): Array&lt;string&gt;
获取系统支持的时区ID。
**系统能力**:SystemCapability.Global.I18n
**返回值:**
| 类型 | 说明 |
| ------ | ----------------------- |
| Array&lt;string&gt; | 系统支持的时区ID列表 |
**示例:**
```
var ids = i18n.TimeZone.getAvailableIDs();
```
### getAvailableZoneCityIDs<sup>9+</sup>
static getAvailableZoneCityIDs(): Array&lt;string&gt;
获取系统支持的时区城市ID。
**系统能力**:SystemCapability.Global.I18n
**返回值:**
| 类型 | 说明 |
| ------ | ----------------------- |
| Array&lt;string&gt; | 系统支持的时区城市ID列表 |
**示例:**
```
var cityIDs = i18n.TimeZone.getAvailableZoneCityIDs();
```
### getCityDisplayName<sup>9+</sup>
static getCityDisplayName(cityID: string, locale: string): string
获取某时区城市在locale下的本地化显示。
**系统能力**:SystemCapability.Global.I18n
**参数:**
| 参数名 | 类型 | 必填 | 说明 |
| ------ | ------ | ---- | ----- |
| cityID | string | 是 | 时区城市ID |
| locale | string | 是 | 区域ID |
**返回值:**
| 类型 | 说明 |
| ------ | ----------------------- |
| string | 时区城市在locale下的本地化显示 |
**示例:**
```
var displayName = i18n.TimeZone.getCityDisplayName("Shanghai", "zh-CN");
```
### getTimezoneFromCity<sup>9+</sup>
static getTimezoneFromCity(cityID: string): TimeZone
创建某时区城市对应的时区对象。
**系统能力**:SystemCapability.Global.I18n
**参数:**
| 参数名 | 类型 | 必填 | 说明 |
| ------ | ------ | ---- | ----- |
| cityID | string | 是 | 时区城市ID |
**返回值:**
| 类型 | 说明 |
| ------ | ----------------------- |
| TimeZone | 时区城市对应的时区对象 |
**示例:**
```
var timezone = i18n.TimeZone.getTimezoneFromCity("Shanghai");
```
## i18n.setUsingLocalDigit<sup>9+</sup>
setUsingLocalDigit(flag: boolean): boolean
设置是否打开本地数字开关。<br>
该接口为系统接口。
**需要权限**:ohos.permission.UPDATE_CONFIGURATION
**系统能力**:SystemCapability.Global.I18n
**参数:**
| 参数名 | 类型 | 必填 | 说明 |
| ------ | ------ | ---- | ----- |
| flag | boolean | 是 | true表示打开本地数字开关,false表示关闭本地数字开关。 |
**返回值:**
| 类型 | 说明 |
| -------- | ------------ |
| boolean | true表示本地数字开关设置成功,false表示本地数字开关设置失败。 |
**示例:**
```
var status = i18n.setUsingLocalDigit(true);
```
## i18n.getUsingLocalDigit<sup>9+</sup>
getUsingLocalDigit(): boolean
获取系统当前是否打开本地数字开关。
**系统能力**:SystemCapability.Global.I18n
**返回值:**
| 类型 | 说明 |
| -------- | ------------ |
| boolean | true表示系统当前已打开本地数字开关,false表示系统当前未打开本地数字开关。 |
**示例:**
```
var status = i18n.getUsingLocalDigit();
``` ```
\ No newline at end of file
...@@ -232,7 +232,7 @@ image.createPixelMap(color, opts) ...@@ -232,7 +232,7 @@ image.createPixelMap(color, opts)
stride: 8, stride: 8,
region: { size: { height: 1, width: 2 }, x: 0, y: 0 } region: { size: { height: 1, width: 2 }, x: 0, y: 0 }
} }
var bufferArr = new Uint8Array(area.pixels); let bufferArr = new Uint8Array(area.pixels);
for (var i = 0; i < bufferArr.length; i++) { for (var i = 0; i < bufferArr.length; i++) {
bufferArr[i] = i + 1; bufferArr[i] = i + 1;
} }
...@@ -263,18 +263,22 @@ writePixels(area: PositionArea, callback: AsyncCallback\<void>): void ...@@ -263,18 +263,22 @@ writePixels(area: PositionArea, callback: AsyncCallback\<void>): void
| 参数名 | 类型 | 必填 | 说明 | | 参数名 | 类型 | 必填 | 说明 |
| --------- | ------------------------------ | ---- | ------------------------------ | | --------- | ------------------------------ | ---- | ------------------------------ |
| area | [PositionArea](#positionarea7) | 是 | 区域,根据区域写入。 | | area | [PositionArea](#positionarea7) | 是 | 区域,根据区域写入。 |
| callback: | AsyncCallback\<void> | 是 | 获取回调,失败时返回错误信息。 | | callback: | AsyncCallback\<void> | 是 | 获取回调,失败时error会返回错误信息。 |
**示例:** **示例:**
```js ```js
pixelmap.writePixels(Area, () => { pixelmap.writePixels(Area, (error) => {
const readArea = { if (error!=undefined) {
pixels: new ArrayBuffer(20), console.info('writePixels failed.');
offset: 0, } else {
stride: 8, const readArea = {
region: { size: { height: 1, width: 2 }, x: 0, y: 0 }, pixels: new ArrayBuffer(20),
} offset: 0,
stride: 8,
region: { size: { height: 1, width: 2 }, x: 0, y: 0 },
}
}
}) })
``` ```
...@@ -890,7 +894,7 @@ packing(source: ImageSource, option: PackingOption, callback: AsyncCallback\<Arr ...@@ -890,7 +894,7 @@ packing(source: ImageSource, option: PackingOption, callback: AsyncCallback\<Arr
**示例:** **示例:**
```js ```js
let packOpts = { format:["image/jpeg"], quality:98 }; let packOpts = { format:"image/jpeg", quality:98 };
imagePackerApi.packing(ImageSourceApi, packOpts, data => {}) imagePackerApi.packing(ImageSourceApi, packOpts, data => {})
``` ```
...@@ -1535,7 +1539,7 @@ PixelMap的初始化选项。 ...@@ -1535,7 +1539,7 @@ PixelMap的初始化选项。
| 名称 | 类型 | 可读 | 可写 | 说明 | | 名称 | 类型 | 可读 | 可写 | 说明 |
| ------- | ------ | ---- | ---- | -------------- | | ------- | ------ | ---- | ---- | -------------- |
| format | string | 是 | 是 | 目标格式。 | | format | string | 是 | 是 | 目标格式。 |
| quality | number | 是 | 是 | 目标图片质量。 | | quality | number | 是 | 是 | JPEG编码中设定输出图片质量的参数,取值范围为1-100。 |
## GetImagePropertyOptions<sup>7+</sup> ## GetImagePropertyOptions<sup>7+</sup>
......
...@@ -885,11 +885,7 @@ once(type: SensorType.SENSOR_TYPE_ID_PROXIMITY, callback: Callback&lt;ProximityR ...@@ -885,11 +885,7 @@ once(type: SensorType.SENSOR_TYPE_ID_PROXIMITY, callback: Callback&lt;ProximityR
**示例:** **示例:**
```js ```js
sensor.once(sensor.SensorType.SENSOR_TYPE_ID_PROXIMITY, function(error, data) { sensor.once(sensor.SensorType.SENSOR_TYPE_ID_PROXIMITY, function(data) {
if (error) {
console.error("Subscription failed. Error code: " + error.code + "; message: " + error.message);
return;
}
console.info('Distance: ' + data.distance); console.info('Distance: ' + data.distance);
} }
); );
...@@ -1349,8 +1345,6 @@ off(type: SensorType.SENSOR_TYPE_ID_HUMIDITY, callback?: Callback&lt;HumidityRes ...@@ -1349,8 +1345,6 @@ off(type: SensorType.SENSOR_TYPE_ID_HUMIDITY, callback?: Callback&lt;HumidityRes
取消订阅传感器数据。 取消订阅传感器数据。
**需要权限**:ohos.permission.READ_HEALTH_DATA,该权限为系统权限
**系统能力**:SystemCapability.Sensors.Sensor **系统能力**:SystemCapability.Sensors.Sensor
**参数:** **参数:**
...@@ -1403,8 +1397,6 @@ sensor.off(sensor.SensorType.SENSOR_TYPE_ID_LINEAR_ACCELERATION, callback); ...@@ -1403,8 +1397,6 @@ sensor.off(sensor.SensorType.SENSOR_TYPE_ID_LINEAR_ACCELERATION, callback);
取消订阅传感器数据。 取消订阅传感器数据。
**需要权限**:ohos.permission.ACCELEROMETER,该权限为系统权限
**系统能力**:SystemCapability.Sensors.Sensor **系统能力**:SystemCapability.Sensors.Sensor
**参数:** **参数:**
...@@ -1486,6 +1478,8 @@ off(type: SensorType.SENSOR_TYPE_ID_PEDOMETER, callback?: Callback&lt;PedometerR ...@@ -1486,6 +1478,8 @@ off(type: SensorType.SENSOR_TYPE_ID_PEDOMETER, callback?: Callback&lt;PedometerR
取消订阅传感器数据。 取消订阅传感器数据。
**需要权限**:ohos.permission.ACTIVITY_MOTION
**系统能力**:SystemCapability.Sensors.Sensor **系统能力**:SystemCapability.Sensors.Sensor
**参数:** **参数:**
...@@ -1898,7 +1892,6 @@ getAngleModify(currentRotationMatrix: Array&lt;number&gt;, preRotationMatrix: Ar ...@@ -1898,7 +1892,6 @@ getAngleModify(currentRotationMatrix: Array&lt;number&gt;, preRotationMatrix: Ar
err.message); err.message);
return; return;
} }
console.info("SensorJsAPI--->Successed to get getAngleModifiy interface get data: " + data.x);
for (var i=0; i < data.length; i++) { for (var i=0; i < data.length; i++) {
console.info("data[" + i + "]: " + data[i]); console.info("data[" + i + "]: " + data[i]);
} }
...@@ -1966,7 +1959,6 @@ createRotationMatrix(rotationVector: Array&lt;number&gt;, callback: AsyncCallbac ...@@ -1966,7 +1959,6 @@ createRotationMatrix(rotationVector: Array&lt;number&gt;, callback: AsyncCallbac
err.message); err.message);
return; return;
} }
console.info("SensorJsAPI--->Successed to get createRotationMatrix interface get data: " + data.x);
for (var i=0; i < data.length; i++) { for (var i=0; i < data.length; i++) {
console.info("data[" + i + "]: " + data[i]); console.info("data[" + i + "]: " + data[i]);
} }
...@@ -2033,7 +2025,6 @@ createQuaternion(rotationVector: Array&lt;number&gt;, callback: AsyncCallback&lt ...@@ -2033,7 +2025,6 @@ createQuaternion(rotationVector: Array&lt;number&gt;, callback: AsyncCallback&lt
err.message); err.message);
return; return;
} }
console.info("SensorJsAPI--->Successed to get createQuaternion interface get data: " + data.x);
for (var i=0; i < data.length; i++) { for (var i=0; i < data.length; i++) {
console.info("data[" + i + "]: " + data[i]); console.info("data[" + i + "]: " + data[i]);
} }
...@@ -2168,7 +2159,6 @@ createRotationMatrix(gravity: Array&lt;number&gt;, geomagnetic: Array&lt;number& ...@@ -2168,7 +2159,6 @@ createRotationMatrix(gravity: Array&lt;number&gt;, geomagnetic: Array&lt;number&
err.message); err.message);
return; return;
} }
console.info("SensorJsAPI--->Successed to get createRotationMatrix interface get data: " + data.x);
for (var i=0; i < data.length; i++) { for (var i=0; i < data.length; i++) {
console.info("data[" + i + "]: " + data[i]) console.info("data[" + i + "]: " + data[i])
} }
......
...@@ -7,6 +7,7 @@ UiTest提供模拟UI操作的能力,供开发者在测试场景使用,主要 ...@@ -7,6 +7,7 @@ UiTest提供模拟UI操作的能力,供开发者在测试场景使用,主要
- [By](#by):提供控件特征描述能力,用于控件筛选匹配查找。 - [By](#by):提供控件特征描述能力,用于控件筛选匹配查找。
- [UiComponent](#uicomponent):代表UI界面上的指定控件,提供控件属性获取,控件点击,滑动查找,文本注入等能力。 - [UiComponent](#uicomponent):代表UI界面上的指定控件,提供控件属性获取,控件点击,滑动查找,文本注入等能力。
- [UiDriver](#uidriver):入口类,提供控件匹配/查找,按键注入,坐标点击/滑动,截图等能能力。 - [UiDriver](#uidriver):入口类,提供控件匹配/查找,按键注入,坐标点击/滑动,截图等能能力。
- [UiWINDOW<sup>9+</sup>](#uiwindow9):入口类,提供窗口属性获取,窗口拖动、调整窗口大小等能能力。
>**说明:** >**说明:**
> >
...@@ -16,7 +17,7 @@ UiTest提供模拟UI操作的能力,供开发者在测试场景使用,主要 ...@@ -16,7 +17,7 @@ UiTest提供模拟UI操作的能力,供开发者在测试场景使用,主要
## 导入模块 ## 导入模块
``` ```
import {UiDriver,BY,MatchPattern} from '@ohos.uitest' import {UiDriver, BY, MatchPattern, ResizeDirection, WindowMode} from '@ohos.uitest'
``` ```
## By ## By
...@@ -28,7 +29,7 @@ By提供的API能力具有以下几个特点:<br>1、支持单属性匹配和多 ...@@ -28,7 +29,7 @@ By提供的API能力具有以下几个特点:<br>1、支持单属性匹配和多
BY.text('123').type('button') BY.text('123').type('button')
``` ```
### By.text ### text
text(txt: string, pattern?: MatchPattern): By text(txt: string, pattern?: MatchPattern): By
...@@ -56,7 +57,7 @@ let by = BY.text('123') //使用静态构造器BY创建by对象,指定目标 ...@@ -56,7 +57,7 @@ let by = BY.text('123') //使用静态构造器BY创建by对象,指定目标
``` ```
### By.key ### key
key(key: string): By key(key: string): By
...@@ -83,7 +84,7 @@ let by = BY.key('123') //使用静态构造器BY创建by对象,指定目标控 ...@@ -83,7 +84,7 @@ let by = BY.key('123') //使用静态构造器BY创建by对象,指定目标控
``` ```
### By.id ### id
id(id: number): By id(id: number): By
...@@ -110,7 +111,7 @@ let by = BY.id(123) //使用静态构造器BY创建by对象,指定目标控件 ...@@ -110,7 +111,7 @@ let by = BY.id(123) //使用静态构造器BY创建by对象,指定目标控件
``` ```
### By.type ### type
type(tp: string): By type(tp: string): By
...@@ -137,7 +138,7 @@ let by = BY.type('button') //使用静态构造器BY创建by对象,指定目 ...@@ -137,7 +138,7 @@ let by = BY.type('button') //使用静态构造器BY创建by对象,指定目
``` ```
### By.clickable ### clickable
clickable(b?: bool): By clickable(b?: bool): By
...@@ -163,7 +164,7 @@ clickable(b?: bool): By ...@@ -163,7 +164,7 @@ clickable(b?: bool): By
let by = BY.clickable(true) //使用静态构造器BY创建by对象,指定目标控件的可点击状态属性。 let by = BY.clickable(true) //使用静态构造器BY创建by对象,指定目标控件的可点击状态属性。
``` ```
### By.longClickable<sup>9+</sup> ### longClickable<sup>9+</sup>
longClickable(b?: bool): By longClickable(b?: bool): By
...@@ -190,7 +191,7 @@ let by = BY.longClickable(true) //使用静态构造器BY创建by对象,指定 ...@@ -190,7 +191,7 @@ let by = BY.longClickable(true) //使用静态构造器BY创建by对象,指定
``` ```
### By.scrollable ### scrollable
scrollable(b?: bool): By scrollable(b?: bool): By
...@@ -216,7 +217,7 @@ scrollable(b?: bool): By ...@@ -216,7 +217,7 @@ scrollable(b?: bool): By
let by = BY.scrollable(true) //使用静态构造器BY创建by对象,指定目标控件的可滑动状态属性。 let by = BY.scrollable(true) //使用静态构造器BY创建by对象,指定目标控件的可滑动状态属性。
``` ```
### By.enabled ### enabled
enabled(b?: bool): By enabled(b?: bool): By
...@@ -242,7 +243,7 @@ enabled(b?: bool): By ...@@ -242,7 +243,7 @@ enabled(b?: bool): By
let by = BY.enabled(true) //使用静态构造器BY创建by对象,指定目标控件的使能状态属性。 let by = BY.enabled(true) //使用静态构造器BY创建by对象,指定目标控件的使能状态属性。
``` ```
### By.focused ### focused
focused(b?: bool): By focused(b?: bool): By
...@@ -268,7 +269,7 @@ focused(b?: bool): By ...@@ -268,7 +269,7 @@ focused(b?: bool): By
let by = BY.focused(true) //使用静态构造器BY创建by对象,指定目标控件的获焦状态属性。 let by = BY.focused(true) //使用静态构造器BY创建by对象,指定目标控件的获焦状态属性。
``` ```
### By.selected ### selected
selected(b?: bool): By selected(b?: bool): By
...@@ -294,7 +295,7 @@ selected(b?: bool): By ...@@ -294,7 +295,7 @@ selected(b?: bool): By
let by = BY.selected(true) //使用静态构造器BY创建by对象,指定目标控件的被选中状态属性。 let by = BY.selected(true) //使用静态构造器BY创建by对象,指定目标控件的被选中状态属性。
``` ```
### By.checked<sup>9+</sup> ### checked<sup>9+</sup>
checked(b?: bool): By checked(b?: bool): By
...@@ -320,7 +321,7 @@ checked(b?: bool): By ...@@ -320,7 +321,7 @@ checked(b?: bool): By
let by = BY.checked(true) //使用静态构造器BY创建by对象,指定目标控件的被勾选状态属性 let by = BY.checked(true) //使用静态构造器BY创建by对象,指定目标控件的被勾选状态属性
``` ```
### By.checkable<sup>9+</sup> ### checkable<sup>9+</sup>
checkable(b?: bool): By checkable(b?: bool): By
...@@ -346,7 +347,7 @@ checkable(b?: bool): By ...@@ -346,7 +347,7 @@ checkable(b?: bool): By
let by = BY.checkable(true) //使用静态构造器BY创建by对象,指定目标控件的能否被勾选状态属性。 let by = BY.checkable(true) //使用静态构造器BY创建by对象,指定目标控件的能否被勾选状态属性。
``` ```
### By.isBefore ### isBefore
isBefore(by: By): By isBefore(by: By): By
...@@ -372,7 +373,7 @@ isBefore(by: By): By ...@@ -372,7 +373,7 @@ isBefore(by: By): By
let by = BY.isBefore(BY.text('123')) //使用静态构造器BY创建by对象,指定目标控件位于给出的特征属性控件之前。 let by = BY.isBefore(BY.text('123')) //使用静态构造器BY创建by对象,指定目标控件位于给出的特征属性控件之前。
``` ```
### By.isAfter ### isAfter
isAfter(by: By): By isAfter(by: By): By
...@@ -403,6 +404,17 @@ let by = BY.isAfter(BY.text('123')) //使用静态构造器BY创建by对象, ...@@ -403,6 +404,17 @@ let by = BY.isAfter(BY.text('123')) //使用静态构造器BY创建by对象,
UiTest中,UiComponent类代表了UI界面上的一个控件,提供控件属性获取,控件点击,滑动查找,文本注入等API。 UiTest中,UiComponent类代表了UI界面上的一个控件,提供控件属性获取,控件点击,滑动查找,文本注入等API。
该类提供的所有方法都使用Promise方式作为异步方法,需使用await调用。 该类提供的所有方法都使用Promise方式作为异步方法,需使用await调用。
### Point<sup>9+</sup>
坐标点信息。
**系统能力**:SystemCapability.Test.UiTest
| 名称 | 参数类型 | 可读 | 可写 | 描述 |
| ---- | -------- | ---- | ---- | ---------------- |
| X | number | 是 | 否 | 坐标点的横坐标。 |
| Y | number | 是 | 否 | 坐标点的纵坐标。 |
### Rect<sup>9+</sup> ### Rect<sup>9+</sup>
控件的边框信息。 控件的边框信息。
...@@ -434,7 +446,7 @@ async function demo() { ...@@ -434,7 +446,7 @@ async function demo() {
} }
``` ```
### UiComponent.doubleClick ### doubleClick
doubleClick(): Promise\<void> doubleClick(): Promise\<void>
...@@ -452,7 +464,7 @@ async function demo() { ...@@ -452,7 +464,7 @@ async function demo() {
} }
``` ```
### UiComponent.longClick ### longClick
longClick(): Promise\<void> longClick(): Promise\<void>
...@@ -470,7 +482,7 @@ async function demo() { ...@@ -470,7 +482,7 @@ async function demo() {
} }
``` ```
### UiComponent.getId ### getId
getId(): Promise\<number> getId(): Promise\<number>
...@@ -494,7 +506,7 @@ async function demo() { ...@@ -494,7 +506,7 @@ async function demo() {
} }
``` ```
### UiComponent.getKey ### getKey
getKey(): Promise\<string> getKey(): Promise\<string>
...@@ -518,7 +530,7 @@ async function demo() { ...@@ -518,7 +530,7 @@ async function demo() {
} }
``` ```
### UiComponent.getText ### getText
getText(): Promise\<string> getText(): Promise\<string>
...@@ -542,7 +554,7 @@ async function demo() { ...@@ -542,7 +554,7 @@ async function demo() {
} }
``` ```
### UiComponent.getType ### getType
getType(): Promise\<string> getType(): Promise\<string>
...@@ -566,7 +578,7 @@ async function demo() { ...@@ -566,7 +578,7 @@ async function demo() {
} }
``` ```
### UiComponent.getBounds<sup>9+</sup> ### getBounds<sup>9+</sup>
getBounds(): Promise\<Rect> getBounds(): Promise\<Rect>
...@@ -590,7 +602,31 @@ async function demo() { ...@@ -590,7 +602,31 @@ async function demo() {
} }
``` ```
### UiComponent.isClickable ### getBoundsCenter<sup>9+</sup>
getBoundsCenter(): Promise\<Point>
获取控件对象的中心点信息。
**系统能力**:SystemCapability.Test.UiTest
**返回值:**
| 类型 | 说明 |
| --------------- | --------------------------------------- |
| Promise\<Point> | 以Promise形式返回控件对象的中心点信息。 |
**示例:**
```js
async function demo() {
let driver = UiDriver.create()
let button = await driver.findComponent(BY.type('button'))
let point = await button.getBoundsCenter()
}
```
### isClickable
isClickable(): Promise\<bool> isClickable(): Promise\<bool>
...@@ -619,7 +655,7 @@ async function demo() { ...@@ -619,7 +655,7 @@ async function demo() {
} }
``` ```
### UiComponent.isLongClickable<sup>9+</sup> ### isLongClickable<sup>9+</sup>
isLongClickable(): Promise\<bool> isLongClickable(): Promise\<bool>
...@@ -648,7 +684,7 @@ async function demo() { ...@@ -648,7 +684,7 @@ async function demo() {
} }
``` ```
### UiComponent.isChecked<sup>9+</sup> ### isChecked<sup>9+</sup>
isChecked(): Promise\<bool> isChecked(): Promise\<bool>
...@@ -677,7 +713,7 @@ async function demo() { ...@@ -677,7 +713,7 @@ async function demo() {
} }
``` ```
### UiComponent.isCheckable<sup>9+</sup> ### isCheckable<sup>9+</sup>
isCheckable(): Promise\<bool> isCheckable(): Promise\<bool>
...@@ -706,7 +742,7 @@ async function demo() { ...@@ -706,7 +742,7 @@ async function demo() {
} }
``` ```
### UiComponent.isScrollable ### isScrollable
isScrollable(): Promise\<bool> isScrollable(): Promise\<bool>
...@@ -736,7 +772,7 @@ async function demo() { ...@@ -736,7 +772,7 @@ async function demo() {
``` ```
### UiComponent.isEnabled ### isEnabled
isEnabled(): Promise\<bool> isEnabled(): Promise\<bool>
...@@ -766,7 +802,7 @@ async function demo() { ...@@ -766,7 +802,7 @@ async function demo() {
``` ```
### UiComponent.isFocused ### isFocused
isFocused(): Promise\<bool> isFocused(): Promise\<bool>
...@@ -795,7 +831,7 @@ async function demo() { ...@@ -795,7 +831,7 @@ async function demo() {
} }
``` ```
### UiComponent.isSelected ### isSelected
isSelected(): Promise\<bool> isSelected(): Promise\<bool>
...@@ -824,7 +860,7 @@ async function demo() { ...@@ -824,7 +860,7 @@ async function demo() {
} }
``` ```
### UiComponent.inputText ### inputText
inputText(text: string): Promise\<void> inputText(text: string): Promise\<void>
...@@ -848,7 +884,7 @@ async function demo() { ...@@ -848,7 +884,7 @@ async function demo() {
} }
``` ```
### UiComponent.clearText<sup>9+</sup> ### clearText<sup>9+</sup>
clearText(): Promise\<void> clearText(): Promise\<void>
...@@ -866,7 +902,7 @@ async function demo() { ...@@ -866,7 +902,7 @@ async function demo() {
} }
``` ```
### UiComponent.scrollSearch ### scrollSearch
scrollSearch(by: By): Promise\<UiComponent> scrollSearch(by: By): Promise\<UiComponent>
...@@ -896,14 +932,20 @@ async function demo() { ...@@ -896,14 +932,20 @@ async function demo() {
} }
``` ```
### UiComponent.scrollToTop<sup>9+</sup> ### scrollToTop<sup>9+</sup>
scrollToTop(): Promise\<void> scrollToTop(speed?: number): Promise\<void>
在控件上滑动到顶部(适用于List等支持滑动的控件)。 在控件上滑动到顶部(适用于List等支持滑动的控件)。
**系统能力**:SystemCapability.Test.UiTest **系统能力**:SystemCapability.Test.UiTest
**参数:**
| 参数名 | 类型 | 必填 | 说明 |
| ------ | ------ | ---- | ---------------------------------------- |
| speed | number | 否 | 滑动速率,默认值为600,单位:像素点/秒。 |
**示例:** **示例:**
```js ```js
...@@ -914,14 +956,20 @@ async function demo() { ...@@ -914,14 +956,20 @@ async function demo() {
} }
``` ```
### UiComponent.scrollToBottom<sup>9+</sup> ### scrollToBottom<sup>9+</sup>
scrollToBottom(): Promise\<void> scrollToBottom(speed?: number): Promise\<void>
在控件上滑动到底部(适用于List等支持滑动的控件)。 在控件上滑动到底部(适用于List等支持滑动的控件)。
**系统能力**:SystemCapability.Test.UiTest **系统能力**:SystemCapability.Test.UiTest
**参数:**
| 参数名 | 类型 | 必填 | 说明 |
| ------ | ------ | ---- | ---------------------------------------- |
| speed | number | 否 | 滑动速率,默认值为600,单位:像素点/秒。 |
**示例:** **示例:**
```js ```js
...@@ -932,7 +980,7 @@ async function demo() { ...@@ -932,7 +980,7 @@ async function demo() {
} }
``` ```
### UiComponent.dragTo<sup>9+</sup> ### dragTo<sup>9+</sup>
dragTo(target: UiComponent): Promise\<void> dragTo(target: UiComponent): Promise\<void>
...@@ -962,7 +1010,7 @@ async function demo() { ...@@ -962,7 +1010,7 @@ async function demo() {
UiDriver类为uitest测试框架的总入口,提供控件匹配/查找,按键注入,坐标点击/滑动,截图等API。 UiDriver类为uitest测试框架的总入口,提供控件匹配/查找,按键注入,坐标点击/滑动,截图等API。
该类提供的方法除UiDriver.create()以外的所有方法都使用Promise方式作为异步方法,需使用await调用。 该类提供的方法除UiDriver.create()以外的所有方法都使用Promise方式作为异步方法,需使用await调用。
### UiDriver.create ### create
static create(): UiDriver static create(): UiDriver
...@@ -984,7 +1032,7 @@ async function demo() { ...@@ -984,7 +1032,7 @@ async function demo() {
} }
``` ```
### UiDriver.delayMs ### delayMs
delayMs(duration: number): Promise\<void> delayMs(duration: number): Promise\<void>
...@@ -1007,7 +1055,7 @@ async function demo() { ...@@ -1007,7 +1055,7 @@ async function demo() {
} }
``` ```
### UiDriver.findComponent ### findComponent
findComponent(by: By): Promise\<UiComponent> findComponent(by: By): Promise\<UiComponent>
...@@ -1036,7 +1084,7 @@ async function demo() { ...@@ -1036,7 +1084,7 @@ async function demo() {
} }
``` ```
### UiDriver.findComponents ### findComponents
findComponents(by: By): Promise\<Array\<UiComponent>> findComponents(by: By): Promise\<Array\<UiComponent>>
...@@ -1065,7 +1113,36 @@ async function demo() { ...@@ -1065,7 +1113,36 @@ async function demo() {
} }
``` ```
### UiDriver.waitForComponent<sup>9+</sup> ### findWindow<sup>9+</sup>
findWindow(filter: WindowFilter): Promise\<UiWindow>
通过指定窗口的属性来查找目标窗口。
**系统能力**:SystemCapability.Test.UiTest
**参数:**
| 参数名 | 类型 | 必填 | 说明 |
| ------ | ------------------------------ | ---- | ---------------- |
| filter | [WindowFilter](#windowfilter9) | 是 | 目标窗口的属性。 |
**返回值:**
| 类型 | 说明 |
| -------------------------------- | ------------------------------------- |
| Promise\<[UiWindow](#uiwindow9)> | 以Promise形式返回找到的目标窗口对象。 |
**示例:**
```js
async function demo() {
let driver = UiDriver.create()
let window = await driver.findWindow({actived: true})
}
```
### waitForComponent<sup>9+</sup>
waitForComponent(by: By, time: number): Promise\<UiComponent> waitForComponent(by: By, time: number): Promise\<UiComponent>
...@@ -1095,7 +1172,7 @@ async function demo() { ...@@ -1095,7 +1172,7 @@ async function demo() {
} }
``` ```
### UiDriver.assertComponentExist ### assertComponentExist
assertComponentExist(by: By): Promise\<void> assertComponentExist(by: By): Promise\<void>
...@@ -1118,7 +1195,7 @@ async function demo() { ...@@ -1118,7 +1195,7 @@ async function demo() {
} }
``` ```
### UiDriver.pressBack ### pressBack
pressBack(): Promise\<void> pressBack(): Promise\<void>
...@@ -1135,7 +1212,7 @@ async function demo() { ...@@ -1135,7 +1212,7 @@ async function demo() {
} }
``` ```
### UiDriver.triggerKey ### triggerKey
triggerKey(keyCode: number): Promise\<void> triggerKey(keyCode: number): Promise\<void>
...@@ -1158,7 +1235,7 @@ async function demo() { ...@@ -1158,7 +1235,7 @@ async function demo() {
} }
``` ```
### UiDriver.click ### click
click(x: number, y: number): Promise\<void> click(x: number, y: number): Promise\<void>
...@@ -1182,7 +1259,7 @@ async function demo() { ...@@ -1182,7 +1259,7 @@ async function demo() {
} }
``` ```
### UiDriver.doubleClick ### doubleClick
doubleClick(x: number, y: number): Promise\<void> doubleClick(x: number, y: number): Promise\<void>
...@@ -1206,7 +1283,7 @@ async function demo() { ...@@ -1206,7 +1283,7 @@ async function demo() {
} }
``` ```
### UiDriver.longClick ### longClick
longClick(x: number, y: number): Promise\<void> longClick(x: number, y: number): Promise\<void>
...@@ -1230,9 +1307,9 @@ async function demo() { ...@@ -1230,9 +1307,9 @@ async function demo() {
} }
``` ```
### UiDriver.swipe ### swipe<sup>9+</sup>
swipe(startx: number, starty: number, endx: number, endy: number): Promise\<void> swipe(startx: number, starty: number, endx: number, endy: number, speed?: number): Promise\<void>
UiDriver对象采取如下操作:从给出的起始坐标点滑向给出的目的坐标点。 UiDriver对象采取如下操作:从给出的起始坐标点滑向给出的目的坐标点。
...@@ -1240,25 +1317,26 @@ UiDriver对象采取如下操作:从给出的起始坐标点滑向给出的目 ...@@ -1240,25 +1317,26 @@ UiDriver对象采取如下操作:从给出的起始坐标点滑向给出的目
**参数:** **参数:**
| 参数名 | 类型 | 必填 | 说明 | | 参数名 | 类型 | 必填 | 说明 |
| ------ | ------ | ---- | -------------------------------------- | | ------ | ------ | ---- | ---------------------------------------- |
| startx | number | 是 | 以number的形式传入起始点的横坐标信息。 | | startx | number | 是 | 以number的形式传入起始点的横坐标信息。 |
| starty | number | 是 | 以number的形式传入起始点的纵坐标信息。 | | starty | number | 是 | 以number的形式传入起始点的纵坐标信息。 |
| endx | number | 是 | 以number的形式传入目的点的横坐标信息。 | | endx | number | 是 | 以number的形式传入目的点的横坐标信息。 |
| endy | number | 是 | 以number的形式传入目的点的纵坐标信息。 | | endy | number | 是 | 以number的形式传入目的点的纵坐标信息。 |
| speed | number | 否 | 滑动速率,默认值为600,单位:像素点/秒。 |
**示例:** **示例:**
```js ```js
async function demo() { async function demo() {
let driver = UiDriver.create() let driver = UiDriver.create()
await driver.swipe(100,100,200,200) await driver.swipe(100,100,200,200,600)
} }
``` ```
### UiDriver.drag<sup>9+</sup> ### drag<sup>9+</sup>
drag(startx: number, starty: number, endx: number, endy: number): Promise\<void> drag(startx: number, starty: number, endx: number, endy: number, speed?: number): Promise\<void>
UiDriver对象采取如下操作:从给出的起始坐标点拖拽至给出的目的坐标点。 UiDriver对象采取如下操作:从给出的起始坐标点拖拽至给出的目的坐标点。
...@@ -1266,23 +1344,24 @@ UiDriver对象采取如下操作:从给出的起始坐标点拖拽至给出的 ...@@ -1266,23 +1344,24 @@ UiDriver对象采取如下操作:从给出的起始坐标点拖拽至给出的
**参数:** **参数:**
| 参数名 | 类型 | 必填 | 说明 | | 参数名 | 类型 | 必填 | 说明 |
| ------ | ------ | ---- | -------------------------------------- | | ------ | ------ | ---- | ---------------------------------------- |
| startx | number | 是 | 以number的形式传入起始点的横坐标信息。 | | startx | number | 是 | 以number的形式传入起始点的横坐标信息。 |
| starty | number | 是 | 以number的形式传入起始点的纵坐标信息。 | | starty | number | 是 | 以number的形式传入起始点的纵坐标信息。 |
| endx | number | 是 | 以number的形式传入目的点的横坐标信息。 | | endx | number | 是 | 以number的形式传入目的点的横坐标信息。 |
| endy | number | 是 | 以number的形式传入目的点的纵坐标信息。 | | endy | number | 是 | 以number的形式传入目的点的纵坐标信息。 |
| speed | number | 否 | 滑动速率,默认值为600,单位:像素点/秒。 |
**示例:** **示例:**
```js ```js
async function demo() { async function demo() {
let driver = UiDriver.create() let driver = UiDriver.create()
await driver.drag(100,100,200,200) await driver.drag(100,100,200,200,600)
} }
``` ```
### UiDriver.screenCap ### screenCap
screenCap(savePath: string): Promise\<bool> screenCap(savePath: string): Promise\<bool>
...@@ -1311,6 +1390,374 @@ async function demo() { ...@@ -1311,6 +1390,374 @@ async function demo() {
} }
``` ```
## UiWindow<sup>9+</sup>
UiTest中,UiWindow类代表了UI界面上的一个窗口,提供窗口属性获取,窗口拖动、调整窗口大小等API。
该类提供的所有方法都使用Promise方式作为异步方法,需使用await调用。
### WindowFilter<sup>9+</sup>
窗口的标志属性信息。
**系统能力**:SystemCapability.Test.UiTest
| 名称 | 参数类型 | 必填 | 可读 | 可写 | 描述 |
| ---------- | -------- | ---- | ---- | ---- | -------------------------- |
| bundleName | string | 否 | 是 | 否 | 窗口对应的包名。 |
| title | string | 否 | 是 | 否 | 窗口的标题。 |
| focused | bool | 否 | 是 | 否 | 窗口是否获焦。 |
| actived | bool | 否 | 是 | 否 | 窗口是否正与用户进行交互。 |
### getBundleName<sup>9+</sup>
getBundleName(): Promise\<string>
获取窗口的包名信息。
**系统能力**:SystemCapability.Test.UiTest
**返回值:**
| 类型 | 说明 |
| ---------------- | --------------------------------- |
| Promise\<string> | 以Promise形式返回窗口的包名信息。 |
**示例:**
```js
async function demo() {
let driver = UiDriver.create()
let window = await driver.findWindow({actived: true})
let name = await window.getBundleName()
```
### getBounds<sup>9+</sup>
getBounds(): Promise\<Rect>
获取窗口的边框信息。
**系统能力**:SystemCapability.Test.UiTest
**返回值:**
| 类型 | 说明 |
| -------------- | --------------------------------- |
| Promise\<Rect> | 以Promise形式返回窗口的边框信息。 |
**示例:**
```js
async function demo() {
let driver = UiDriver.create()
let window = await driver.findWindow({actived: true})
let rect = await window.getBounds()
}
```
### getTitle<sup>9+</sup>
getTitle(): Promise\<string>
获取窗口的标题信息。
**系统能力**:SystemCapability.Test.UiTest
**返回值:**
| 类型 | 说明 |
| ---------------- | --------------------------------- |
| Promise\<string> | 以Promise形式返回窗口的标题信息。 |
**示例:**
```js
async function demo() {
let driver = UiDriver.create()
let window = await driver.findWindow({actived: true})
let rect = await window.getTitle()
}
```
### getWindowMode<sup>9+</sup>
getWindowMode(): Promise\<WindowMode>
获取窗口的窗口模式信息。
**系统能力**:SystemCapability.Test.UiTest
**返回值:**
| 类型 | 说明 |
| ------------------------------------------------ | ------------------------------------- |
| Promise\<[WindowMode](#WindowMode<sup>9+</sup>)> | 以Promise形式返回窗口的窗口模式信息。 |
**示例:**
```js
async function demo() {
let driver = UiDriver.create()
let window = await driver.findWindow({actived: true})
let mode = await window.getWindowMode()
}
```
### isFocused<sup>9+</sup>
isFocused(): Promise\<bool>
判断窗口是否获焦。
**系统能力**:SystemCapability.Test.UiTest
**返回值:**
| 类型 | 说明 |
| -------------- | ----------------------------------- |
| Promise\<bool> | 以Promise形式返回窗口对象是否获焦。 |
**示例:**
```js
async function demo() {
let driver = UiDriver.create()
let window = await driver.findWindow({actived: true})
let focused = await window.isFocused()
}
```
### isActived<sup>9+</sup>
isActived(): Promise\<bool>
判断窗口是否为用户交互窗口。
**系统能力**:SystemCapability.Test.UiTest
**返回值:**
| 类型 | 说明 |
| -------------- | --------------------------------------------- |
| Promise\<bool> | 以Promise形式返回窗口对象是否为用户交互窗口。 |
**示例:**
```js
async function demo() {
let driver = UiDriver.create()
let window = await driver.findWindow({actived: true})
let focused = await window.isActived()
}
```
### focus<sup>9+</sup>
focus(): Promise\<bool>
让窗口获焦。
**系统能力**:SystemCapability.Test.UiTest
**返回值:**
| 类型 | 说明 |
| -------------- | ----------------------------------- |
| Promise\<bool> | 以Promise形式返回操作是否成功完成。 |
**示例:**
```js
async function demo() {
let driver = UiDriver.create()
let window = await driver.findWindow({actived: true})
await window.focus()
}
```
### moveTo<sup>9+</sup>
moveTo(x: number, y: number): Promise\<bool>;
将窗口移动到目标点。适用于支持移动的窗口。
**系统能力**:SystemCapability.Test.UiTest
**参数:**
| 参数名 | 类型 | 必填 | 说明 |
| ------ | ------ | ---- | -------------------------------------- |
| x | number | 是 | 以number的形式传入目标点的横坐标信息。 |
| y | number | 是 | 以number的形式传入目标点的纵坐标信息。 |
**返回值:**
| 类型 | 说明 |
| -------------- | ----------------------------------- |
| Promise\<bool> | 以Promise形式返回操作是否成功完成。 |
**示例:**
```js
async function demo() {
let driver = UiDriver.create()
let window = await driver.findWindow({actived: true})
await window.moveTo(100, 100)
}
```
### resize<sup>9+</sup>
resize(wide: number, height: number, direction: ResizeDirection): Promise\<bool>
根据传入的宽、高和调整方向来调整窗口的大小。适用于支持大小调整的窗口。
**系统能力**:SystemCapability.Test.UiTest
**参数:**
| 参数名 | 类型 | 必填 | 说明 |
| --------- | ------------------------------------------------ | ---- | ------------------------------------------------------------ |
| wide | number | 是 | 以number的形式传入调整后窗口的宽度。 |
| height | number | 是 | 以number的形式传入调整后窗口的高度。 |
| direction | [ResizeDirection](#resizedirection<sup>9+</sup>) | 是 | 以[ResizeDirection](#ResizeDirection<sup>9+</sup>)的形式传入窗口调整的方向。 |
**返回值:**
| 类型 | 说明 |
| -------------- | ----------------------------------- |
| Promise\<bool> | 以Promise形式返回操作是否成功完成。 |
**示例:**
```js
async function demo() {
let driver = UiDriver.create()
let window = await driver.findWindow({actived: true})
await window.resize(100, 100, ResizeDirection.LEFT)
}
```
### split<sup>9+</sup>
split(): Promise\<bool>
将窗口模式切换成分屏模式。适用于支持切屏操作的窗口。
**系统能力**:SystemCapability.Test.UiTest
**返回值:**
| 类型 | 说明 |
| -------------- | ----------------------------------- |
| Promise\<bool> | 以Promise形式返回操作是否成功完成。 |
**示例:**
```js
async function demo() {
let driver = UiDriver.create()
let window = await driver.findWindow({actived: true})
await window.split()
}
```
### maximize<sup>9+</sup>
maximize(): Promise\<bool>
将窗口最大化。适用于支持窗口最大化操作的窗口。
**系统能力**:SystemCapability.Test.UiTest
**返回值:**
| 类型 | 说明 |
| -------------- | ----------------------------------- |
| Promise\<bool> | 以Promise形式返回操作是否成功完成。 |
**示例:**
```js
async function demo() {
let driver = UiDriver.create()
let window = await driver.findWindow({actived: true})
await window.maximize()
}
```
### minimize<sup>9+</sup>
minimize(): Promise\<bool>
将窗口最小化。适用于支持窗口最小化操作的窗口。
**系统能力**:SystemCapability.Test.UiTest
**返回值:**
| 类型 | 说明 |
| -------------- | ----------------------------------- |
| Promise\<bool> | 以Promise形式返回操作是否成功完成。 |
**示例:**
```js
async function demo() {
let driver = UiDriver.create()
let window = await driver.findWindow({actived: true})
await window.minimize()
}
```
### resume<sup>9+</sup>
resume(): Promise\<bool>
将窗口恢复到之前的窗口模式。
**系统能力**:SystemCapability.Test.UiTest
**返回值:**
| 类型 | 说明 |
| -------------- | ----------------------------------- |
| Promise\<bool> | 以Promise形式返回操作是否成功完成。 |
**示例:**
```js
async function demo() {
let driver = UiDriver.create()
let window = await driver.findWindow({actived: true})
await window.resume()
}
```
### close<sup>9+</sup>
close(): Promise\<bool>
将窗口关闭。
**系统能力**:SystemCapability.Test.UiTest
**返回值:**
| 类型 | 说明 |
| -------------- | ----------------------------------- |
| Promise\<bool> | 以Promise形式返回操作是否成功完成。 |
**示例:**
```js
async function demo() {
let driver = UiDriver.create()
let window = await driver.findWindow({actived: true})
await window.close()
}
```
## MatchPattern ## MatchPattern
控件属性支持的匹配模式。 控件属性支持的匹配模式。
...@@ -1323,3 +1770,33 @@ async function demo() { ...@@ -1323,3 +1770,33 @@ async function demo() {
| CONTAINS | 1 | 包含给定值。 | | CONTAINS | 1 | 包含给定值。 |
| STARTS_WITH | 2 | 从给定值开始。 | | STARTS_WITH | 2 | 从给定值开始。 |
| ENDS_WITH | 3 | 以给定值结束。 | | ENDS_WITH | 3 | 以给定值结束。 |
## ResizeDirection<sup>9+</sup>
窗口调整大小的方向。
**系统能力**:以下各项对应的系统能力均为SystemCapability.Test.UiTest
| 名称 | 说明 |
| ---------- | -------- |
| LEFT | 左方。 |
| RIGHT | 右方。 |
| UP | 上方。 |
| DOWN | 下方。 |
| LEFT_UP | 左上方。 |
| LEFT_DOWN | 左下方。 |
| RIGHT_UP | 右上方。 |
| RIGHT_DOWN | 右下方。 |
## WindowMode<sup>9+</sup>
窗口的窗口模式。
**系统能力**:以下各项对应的系统能力均为SystemCapability.Test.UiTest
| 名称 | 说明 |
| ---------- | ---------- |
| FULLSCREEN | 全屏模式。 |
| PRIMARY | 主窗口。 |
| SECONDARY | 第二窗口。 |
| FLOAT | 浮动窗口。 |
...@@ -81,7 +81,8 @@ push(param: PushParameters, callback: AsyncCallback&lt;void&gt;): void ...@@ -81,7 +81,8 @@ push(param: PushParameters, callback: AsyncCallback&lt;void&gt;): void
| extraData | KVObject | 否 | 附加数据值。 | | extraData | KVObject | 否 | 附加数据值。 |
- 示例 - 示例
[组件使用者调用接口](#组件使用者调用接口)示例。
[Plugin组件提供方](#组件提供方)示例。
## request ## request
...@@ -117,7 +118,8 @@ request(param: RequestParameters, callback: AsyncCallback&lt;RequestCallbackPara ...@@ -117,7 +118,8 @@ request(param: RequestParameters, callback: AsyncCallback&lt;RequestCallbackPara
- 示例 - 示例
[组件使用者调用接口](#组件使用者调用接口)示例。
[Plugin组件使用方](#组件使用方)示例。
## on ## on
...@@ -146,22 +148,23 @@ on(eventType: string, callback: OnPushEventCallback | OnRequestEventCallback): v ...@@ -146,22 +148,23 @@ on(eventType: string, callback: OnPushEventCallback | OnRequestEventCallback): v
| extraData | KVObjec | 附加数据。 | | extraData | KVObjec | 附加数据。 |
- 示例 - 示例
[组件使用者调用接口](#组件使用者调用接口)示例。
[Plugin组件工具](#Plugin组件工具)示例。
## 示例 ## 示例
### 使用PluginComponent组件 ### 组件使用方
``` ```ts
import plugin from "../../test/plugin_component.js" //PluginUserExample.ets
import plugincomponent from '@ohos.plugincomponent' import plugin from "plugin_component.js"
@Entry @Entry
@Component @Component
struct PluginComponentExample { struct PluginUserExample {
@StorageLink("plugincount") plugincount: Object[] = [ @StorageLink("plugincount") plugincount: Object[] = [
{ source: 'plugincomponent1', ability: 'com.example.plugin' }, { source: 'plugincomponent1', ability: 'com.example.plugin' },
{ source: 'plugintemplate', ability: 'com.example.myapplication' }, { source: 'plugintemplate', ability: 'com.example.myapplication' },
...@@ -172,32 +175,23 @@ struct PluginComponentExample { ...@@ -172,32 +175,23 @@ struct PluginComponentExample {
Text('Hello World') Text('Hello World')
.fontSize(50) .fontSize(50)
.fontWeight(FontWeight.Bold) .fontWeight(FontWeight.Bold)
Button('Push') Button('Register Request Listener')
.fontSize(50) .fontSize(30)
.width(400)
.height(100)
.onClick(() => {
plugin.Push()
console.log("Button('Push')")
})
.margin({ top: 20 })
Button('Request1')
.fontSize(50)
.width(400) .width(400)
.height(100) .height(100)
.margin({ top: 20 }) .margin({top:20})
.onClick(() => { .onClick(()=>{
plugin.Request1() plugin.onListener()
console.log("Button('Request1')") console.log("Button('Register Request Listener')")
}) })
Button('Request2') Button('Request')
.fontSize(50) .fontSize(50)
.width(400) .width(400)
.height(100) .height(100)
.margin({ top: 20 }) .margin({ top: 20 })
.onClick(() => { .onClick(() => {
plugin.Request2() plugin.Request()
console.log("Button('Request2')") console.log("Button('Request')")
}) })
ForEach(this.plugincount, item => { ForEach(this.plugincount, item => {
PluginComponent({ PluginComponent({
...@@ -214,15 +208,58 @@ struct PluginComponentExample { ...@@ -214,15 +208,58 @@ struct PluginComponentExample {
} }
.width('100%') .width('100%')
.height('100%') .height('100%')
}
} }
``` ```
### 组件提供方
### 组件使用者调用接口 ```ts
//PluginProviderExample.ets
import plugin from "plugin_component.js"
@Entry
@Component
struct PluginProviderExample {
@State message: string = 'no click!'
build() {
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
Button('Register Push Listener')
.fontSize(30)
.width(400)
.height(100)
.margin({top:20})
.onClick(()=>{
plugin.onListener()
console.log("Button('Register Push Listener')")
})
Button('Push')
.fontSize(30)
.width(400)
.height(100)
.margin({top:20})
.onClick(()=>{
plugin.Push()
this.message = "Button('Push')"
console.log("Button('Push')")
})
Text(this.message)
.height(150)
.fontSize(30)
.padding(5)
.margin(5)
}.width('100%').height('100%').backgroundColor(0xDCDCDC).padding({ top: 5 })
}
}
``` ```
import pluginComponentManager from '@ohos.plugincomponent'
### Plugin组件工具
```js
//plugin_component.js
import pluginComponentManager from '@ohos.pluginComponent'
function onPushListener(source, template, data, extraData) { function onPushListener(source, template, data, extraData) {
console.log("onPushListener template.source=" + template.source) console.log("onPushListener template.source=" + template.source)
...@@ -239,14 +276,23 @@ function onPushListener(source, template, data, extraData) { ...@@ -239,14 +276,23 @@ function onPushListener(source, template, data, extraData) {
console.log("onPushListener extraData=" + JSON.stringify(extraData)) console.log("onPushListener extraData=" + JSON.stringify(extraData))
} }
function onRequestListener(source, name, data)
{
console.log("onRequestListener name=" + name);
console.log("onRequestListener data=" + JSON.stringify(data));
return {template:"plugintemplate", data:data};
}
export default { export default {
//register listener //register listener
onListener() { onListener() {
pluginComponentManager.on("push", onPushListener) pluginComponentManager.on("push", onPushListener)
pluginComponentManager.on("request", onRequestListener)
}, },
Request() { Push() {
// 组件使用者主动发送事件 // 组件提供方主动发送事件
pluginComponentManager.request({ pluginComponentManager.push(
{
want: { want: {
bundleName: "com.example.myapplication", bundleName: "com.example.myapplication",
abilityName: "com.example.myapplication.MainAbility", abilityName: "com.example.myapplication.MainAbility",
...@@ -256,43 +302,19 @@ export default { ...@@ -256,43 +302,19 @@ export default {
"key_1": "plugin component test", "key_1": "plugin component test",
"key_2": 34234 "key_2": 34234
}, },
jsonPath: "assets/js", extraData: {
"extra_str": "this is push event"
},
jsonPath: "",
}, },
(err, data) => { (err, data) => {
console.log("request_callback1: componentTemplate.ability=" + data.componentTemplate.ability) console.log("push_callback: push ok!");
console.log("request_callback1: componentTemplate.source=" + data.componentTemplate.source)
var jsonObject = JSON.parse(data.componentTemplate.source)
console.log("request_callback1:source json object" + jsonObject)
var jsonArry = jsonObject.ExternalComponent
for (var i in jsonArry) {
console.log(jsonArry[i])
}
console.log("request_callback1:source json string" + JSON.stringify(jsonObject))
console.log("request_callback1: data=" + JSON.stringify(data.data))
console.log("request_callback1: extraData=" + JSON.stringify(data.extraData))
} }
) )
}
}
// 组件提供者使用接口示例
import pluginComponentManager from '@ohos.plugincomponent'
function onRequestListener(source, name, data) {
console.log("onRequestListener name=" + name)
console.log("onRequestListener data=" + JSON.stringify(data))
return { template: "plugintemplate", data: data }
}
export default {
//register listener
onListener() {
pluginComponentManager.on("request", onRequestListener)
}, },
Push() { Request() {
// 组件提供者主动发送事件 // 组件使用方主动发送事件
pluginComponentManager.push( pluginComponentManager.request({
{
want: { want: {
bundleName: "com.example.myapplication", bundleName: "com.example.myapplication",
abilityName: "com.example.myapplication.MainAbility", abilityName: "com.example.myapplication.MainAbility",
...@@ -302,17 +324,22 @@ export default { ...@@ -302,17 +324,22 @@ export default {
"key_1": "plugin component test", "key_1": "plugin component test",
"key_2": 34234 "key_2": 34234
}, },
extraData: { jsonPath: "",
"extra_str": "this is push event"
},
jsonPath: "assets/js",
}, },
(err, data) => { (err, data) => {
console.log("push_callback1: componentTemplate.ability=" + data.componentTemplate.ability) console.log("request_callback: componentTemplate.ability=" + data.componentTemplate.ability)
console.log("push_callback1: componentTemplate.source=" + data.componentTemplate.source) console.log("request_callback: componentTemplate.source=" + data.componentTemplate.source)
console.log("push ok!") var jsonObject = JSON.parse(data.componentTemplate.source)
console.log("request_callback:source json object" + jsonObject)
var jsonArry = jsonObject.ExternalComponent
for (var i in jsonArry) {
console.log(jsonArry[i])
}
console.log("request_callback:source json string" + JSON.stringify(jsonObject))
console.log("request_callback: data=" + JSON.stringify(data.data))
console.log("request_callback: extraData=" + JSON.stringify(data.extraData))
} }
) )
}, }
} }
``` ```
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
| 名称 | 参数类型 | 默认值 | 描述 | | 名称 | 参数类型 | 默认值 | 描述 |
| -------- | -------- | -------- | -------- | | -------- | -------- | -------- | -------- |
| motionPath | {<br/>path:&nbsp;string,<br/>from?:&nbsp;number,<br/>to?:&nbsp;number,<br/>rotatable?:&nbsp;boolean<br/>}<br/>>&nbsp;&nbsp;**说明:**<br/>>&nbsp;path中支持通过start和end进行起点和终点的替代,如:<br/>>&nbsp;<br/>>&nbsp;'Mstart.x&nbsp;start.y&nbsp;L50&nbsp;50&nbsp;Lend.x&nbsp;end.y&nbsp;Z'。 | {<br/>"",<br/>0.0,<br/>1.0,<br/>false<br/>} | 设置组件的运动路径,入参说明如下:<br/>-&nbsp;path:位移动画的运动路径,使用svg路径字符串。<br/>-&nbsp;from:运动路径的起点,默认为0.0。<br/>-&nbsp;to:运动路径的终点,默认为1.0。<br/>-&nbsp;rotatable:是否跟随路径进行旋转。 | | motionPath | {<br/>path:&nbsp;string,<br/>from?:&nbsp;number,<br/>to?:&nbsp;number,<br/>rotatable?:&nbsp;boolean<br/>}<br/>**说明:**<br/>path中支持通过start和end进行起点和终点的替代,如:<br/>'Mstart.x&nbsp;start.y&nbsp;L50&nbsp;50&nbsp;Lend.x&nbsp;end.y&nbsp;Z'| {<br/>"",<br/>0.0,<br/>1.0,<br/>false<br/>} | 设置组件的运动路径,入参说明如下:<br/>-&nbsp;path:位移动画的运动路径,使用svg路径字符串。<br/>-&nbsp;from:运动路径的起点,默认为0.0。<br/>-&nbsp;to:运动路径的终点,默认为1.0。<br/>-&nbsp;rotatable:是否跟随路径进行旋转。 |
## 示例 ## 示例
......
...@@ -42,7 +42,7 @@ OpenHarmony提供了九种后台模式,供需要在后台做长时任务的业 ...@@ -42,7 +42,7 @@ OpenHarmony提供了九种后台模式,供需要在后台做长时任务的业
**表1** 长时任务种类 **表1** 长时任务种类
| BackgroundMode | 说明 | 通知栏显示提示 | 备注 | | 后台模式 | 说明 | 通知栏显示提示 | 备注 |
| -------- | -------- | -------- | -------- | | -------- | -------- | -------- | -------- |
| dataTransfer | 通过网络/对端设备进行数据下载、备份、分享、传输等 | 正在运行数据传输任务 | - | | dataTransfer | 通过网络/对端设备进行数据下载、备份、分享、传输等 | 正在运行数据传输任务 | - |
| audioPlayback | 音频输出 | 正在运行音频播放任务 | - | | audioPlayback | 音频输出 | 正在运行音频播放任务 | - |
......
...@@ -6,14 +6,14 @@ ...@@ -6,14 +6,14 @@
| ---- | --------------------------------- | ------------------------------------------------------------ | | ---- | --------------------------------- | ------------------------------------------------------------ |
| 1 | 客户化写作基本要求 | **写作中,请变身开发者,对于开发者使用该API时所需的使用场景、参数选取原则、开发建议/经验、示例等信息进行清晰描述,达到指导开发者顺利使用本API进行开发的目标。** | | 1 | 客户化写作基本要求 | **写作中,请变身开发者,对于开发者使用该API时所需的使用场景、参数选取原则、开发建议/经验、示例等信息进行清晰描述,达到指导开发者顺利使用本API进行开发的目标。** |
| 2 | | **所有的写作说明,在完成写作后,都要删除。** | | 2 | | **所有的写作说明,在完成写作后,都要删除。** |
| 3 | 上传路径 | markdown文件:docs/zh-cn/application-dev/reference/apis<br>图片路径:docs/zh-cn/application-dev/reference/apis/figures,并在markdown文件中通过路径`![](figures/xxx.jpg)`引用。 | | 3 | 上传路径 | markdown文件:docs/zh-cn/application-dev/reference/apis<br>图片路径:docs/zh-cn/application-dev/reference/apis/figures,并在markdown文件中通过路径`![](figures/xxx.jpg)``![](figures/xxx.png)`引用。 |
| 4 | 文件命名 | 一个d.ts对应一个js api文档,文件名称应与模块名称保持一致,格式为:**js-apis-模块名.md**<br/>示例:<br/>媒体@ohos.multimedia.audio,文件命名为:js-apis-audio.md<br/>电话@ohos.telephony.sms,文件命名为:js-apis-sms.md | | 4 | 文件命名 | 一个d.ts对应一个js api文档,文件名称应与模块名称保持一致,格式为:**js-apis-模块名.md**<br/>示例:<br/>媒体@ohos.multimedia.audio,文件命名为:js-apis-audio.md<br/>电话@ohos.telephony.sms,文件命名为:js-apis-sms.md |
| 5 | 目录修改 | 新增文件,需要修改对应的Readme,即`docs/zh-cn/application-dev/reference/apis/Readme-CN.md`。 | | 5 | 目录修改 | 新增文件,需要修改对应的Readme,即`docs/zh-cn/application-dev/reference/apis/Readme-CN.md`。 |
| 6 | 文档结构 | - 模块说明<br/>- 起始版本说明<br/>- 导入模块/使用说明<br/>- 接口(属性、方法、枚举、自定义类型)<br/> 描述顺序和代码保持一致,如果某些接口具有逻辑顺序,请注意排列。 | | 6 | 文档结构 | - 模块说明<br/>- 起始版本说明<br/>- 导入模块/使用说明<br/>- 接口(属性、方法、枚举、自定义类型)<br/> 描述顺序和代码保持一致,如果某些接口具有逻辑顺序,请注意排列。 |
| 7 | 接口版本说明 | 1. 每个模块要有起始版本说明,使用引用语法“>”对接口的起始版本进行说明。接口没有标记的,默认与模块同一个起始版本。<br/>2. 已有模块新增接口使用\<sup>标签标记对应版本号。<br/> 示例:API 6已有的模块,在API 7新增了一个属性字段,则在属性后加标记,即newAttribute<sup>7+</sup><br/> 写法:`<sup>7+</sup>`<br/> 如果新增了一个方法,则在方法标题后增加标记,即 sim.getSimIccId<sup>7+</sup>,interface、class、枚举等同理。 | | 7 | 接口版本说明 | 1. 每个模块要有起始版本说明,使用引用语法“>”对接口的起始版本进行说明。接口没有标记的,默认与模块同一个起始版本。<br/>2. 已有模块新增接口使用\<sup>标签标记对应版本号。写法:`<sup>版本号+</sup>`<br/> 例如`<sup>7+</sup>`<br/> 示例:API 6已有的模块,在API 7新增了一个属性字段,则在属性后加标记,即newAttribute<sup>7+</sup><br/>如果新增了一个方法,则在方法标题后增加标记,即 sim.getSimIccId<sup>7+</sup>,interface、class、枚举等同理。 |
| 8 | 废弃接口说明 | 废弃内容不能直接删去,在废弃内容后面加标注deprecated,并使用“>”引用语法建议使用的替代方式,加上对应的链接。<br/>示例:abandonmentMethod<sup>(deprecated) </sup><br/>> 从API Version 7 开始不再维护,建议使用[newMethod]\(#newMethod)替代。 | | 8 | 废弃接口说明 | 废弃内容不能直接删去,在废弃内容后面加标注deprecated,并使用“>”引用语法建议使用的替代方式,加上对应的链接。<br/>示例:abandonmentMethod<sup>(deprecated) </sup><br/>> 从API Version 7 开始不再维护,建议使用[newMethod]\(#newmethod)替代。 |
| 9 | 权限说明 | 与代码保持一致,下沉到各个方法、枚举、属性字段中。<br/>1. 如果仅系统应用可申请,格式:<br/> **需要权限:** ohos.permission.xxxx,仅系统应用可用。<br/>2. 如果该权限所有应用可申请,格式:<br/> **需要权限:** ohos.permission.xxxx <br/>3. 如果该接口涉及多个权限,则采用“和、或”进行分割,格式:<br/> **需要权限:** ohos.permission.A 和 ohos.permission.B<br/> **需要权限:** ohos.permission.A 或 ohos.permission.B | | 9 | 权限说明 | 与代码保持一致,下沉到各个方法、枚举、属性字段中。<br/>1. 如果仅系统应用可申请,格式:<br/> **需要权限:** ohos.permission.xxxx,仅系统应用可用。<br/>2. 如果该权限所有应用可申请,格式:<br/> **需要权限:** ohos.permission.xxxx <br/>3. 如果该接口涉及多个权限,则采用“和、或”进行分割,格式:<br/> **需要权限:** ohos.permission.A 和 ohos.permission.B<br/> **需要权限:** ohos.permission.A 或 ohos.permission.B |
| 10 | @syscap | 1. 每个方法都需要进行描述,格式:<br/> **系统能力**:SystemCapability.xxx.xxx<br/>2. 每个表格(属性、枚举、常量、变量)可统一进行说明,分两种情况:<br/> 1)每个表格下系统能力无差异的,同方法的写法:<br/> **系统能力**:SystemCapability.xxx.xxx<br/> 2)有差异的:<br/> 以下各项对应的系统能力有所不同,详见下表。<br/> 然后在每一个表格项里进行描述。 | | 10 | @syscap | 1. 每个方法都需要进行描述,格式:<br/> **系统能力**:SystemCapability.xxx.xxx<br/>2. 每个表格(属性、枚举、常量、变量)可统一进行说明,分两种情况:<br/> 1)每个表格下系统能力无差异的,同方法的写法:<br/> **系统能力**:SystemCapability.xxx.xxx<br/> 2)有差异的:在每一个表格项里进行描述。 |
| 11 | @system api | 1. 如果某个模块全部接口均为system api,则在模块开头的版本说明下一行,增加:<br/> - 本模块接口为系统接口。<br/>2. 如果某个接口为system api,仅供OEM厂商使用,则需要在描述中增加:<br/> 此接口为系统接口。 | | 11 | @system api | 1. 如果某个模块全部接口均为system api,则在模块开头的版本说明下一行,增加:<br/> - 本模块接口为系统接口。<br/>2. 如果某个接口为system api,仅供OEM厂商使用,则需要在描述中增加:<br/> 此接口为系统接口。 |
| 12 | @FAModelOnly<br/>@StageModelOnly | 1. 如果某个模块均只针对某模型实现,则在模块开头的版本说明下一行,增加:<br/> - 本模块接口仅可在FA模型/Stage模型下使用。<br/>2. 如果某个接口只针对某模型实现,则需要在描述中增加:<br/> 此接口仅可在FA模型/Stage模型下使用。 | | 12 | @FAModelOnly<br/>@StageModelOnly | 1. 如果某个模块均只针对某模型实现,则在模块开头的版本说明下一行,增加:<br/> - 本模块接口仅可在FA模型/Stage模型下使用。<br/>2. 如果某个接口只针对某模型实现,则需要在描述中增加:<br/> 此接口仅可在FA模型/Stage模型下使用。 |
| 13 | 异步接口说明(callback、Promise) | 对于callback、Promise在方法描述、参数说明、返回值说明的具体描述要求如下:<br/>**callback**的固定句式:<br/>方法介绍:xxx(方法描述)。使用callback异步回调。<br/>参数说明:<br/>**callback\<boolean>**:回调函数。返回true表示xxx;返回false表示xxx。<br/>**callback\<Object>**:回调函数,返回xxx。例如”回调函数,返回音频采集器对象。“<br/>**AsyncCallback\<void>**:回调函数。当具体的操作(视具体接口功能描述)成功,err为undefined,否则为错误对象。<br/>**AsyncCallback\<Object x>**:回调函数。当具体的操作(视具体接口功能描述)成功,err为undefined,data为获取到的Object x;否则为错误对象。<br/>**Promise**的固定句式:<br/>方法介绍:xxx(方法描述)。使用Promise异步回调。<br/>参数说明:<br/>**Promise\<boolean>**:Promise对象。返回true表示xxx;返回false表示xxx。<br/>**Promise\<Object>**:Promise对象,返回xxx。例如”Promise对象,返回音频采集器对象。“<br/>**Promise\<void>**:Promise对象。无返回结果的Promise对象。 | | 13 | 异步接口说明(callback、Promise) | 对于callback、Promise在方法描述、参数说明、返回值说明的具体描述要求如下:<br/>**callback**的固定句式:<br/>方法介绍:xxx(方法描述)。使用callback异步回调。<br/>参数说明:<br/>**callback\<boolean>**:回调函数。返回true表示xxx;返回false表示xxx。<br/>**callback\<Object>**:回调函数,返回xxx。例如”回调函数,返回音频采集器对象。“<br/>**AsyncCallback\<void>**:回调函数。当具体的操作(视具体接口功能描述)成功,err为undefined,否则为错误对象。<br/>**AsyncCallback\<Object x>**:回调函数。当具体的操作(视具体接口功能描述)成功,err为undefined,data为获取到的Object x;否则为错误对象。<br/>**Promise**的固定句式:<br/>方法介绍:xxx(方法描述)。使用Promise异步回调。<br/>参数说明:<br/>**Promise\<boolean>**:Promise对象。返回true表示xxx;返回false表示xxx。<br/>**Promise\<Object>**:Promise对象,返回xxx。例如”Promise对象,返回音频采集器对象。“<br/>**Promise\<void>**:Promise对象。无返回结果的Promise对象。 |
...@@ -274,7 +274,7 @@ import call from '@ohos.telephony.call'; ...@@ -274,7 +274,7 @@ import call from '@ohos.telephony.call';
| 名称 | 类型 | 可读 | 可写 | 说明 | | 名称 | 类型 | 可读 | 可写 | 说明 |
| ------------ | ------------------- | ---- | ---- | ------------------------------------------------------------ | | ------------ | ------------------- | ---- | ---- | ------------------------------------------------------------ |
| parameterUrl | string | 是 | 是 | 媒体输出URI。支持: 1. 协议类型为“internal”的相对路径,示例如下: 临时目录:internal://cache/test.mp4 2. 文件的绝对路径,示例如下: file:///data/data/ohos.xxx.xxx/files/test.mp4 | | parameterUrl | string | 是 | 是 | 媒体输出URI。支持: <br/>1. 协议类型为“internal”的相对路径,示例如下: 临时目录:internal://cache/test.mp4 <br/>2. 文件的绝对路径,示例如下: file:///data/data/ohos.xxx.xxx/files/test.mp4 |
| parameterOne | [CustomEnum](#枚举) | 是 | 是 | 属性描述,要求与参数说明类似。 | | parameterOne | [CustomEnum](#枚举) | 是 | 是 | 属性描述,要求与参数说明类似。 |
## 变更日志 ## 变更日志
......
...@@ -101,7 +101,7 @@ OpenHarmony参考机械装配领域的零部件的概念将系统能力抽象为 ...@@ -101,7 +101,7 @@ OpenHarmony参考机械装配领域的零部件的概念将系统能力抽象为
| ------------ | ------------------------------------------------------------ | | ------------ | ------------------------------------------------------------ |
| 英文名称 | 名词形式,需体现部件的功能,在系统内全局唯一,不超过63个有效英文字符,使用小写加下划线的内核风格命名,例如:unix_like。 | | 英文名称 | 名词形式,需体现部件的功能,在系统内全局唯一,不超过63个有效英文字符,使用小写加下划线的内核风格命名,例如:unix_like。 |
| 中文名称 | 名词形式,需体现部件的功能,不超过16个中文字符,不建议中英文混合。 | | 中文名称 | 名词形式,需体现部件的功能,不超过16个中文字符,不建议中英文混合。 |
| 子系统 | 部件归属的子系统 | | 子系统 | 部件归属的子系统 |
| 功能描述 | 一句话简要描述部件功能,100字以内。 | | 功能描述 | 一句话简要描述部件功能,100字以内。 |
| 可配置特性 | 部件对外可配置的特性。 | | 可配置特性 | 部件对外可配置的特性。 |
| 适用系统类型 | 部件适用的系统类型:小型、轻量和标准,可以同时支持多种。 | | 适用系统类型 | 部件适用的系统类型:小型、轻量和标准,可以同时支持多种。 |
......
# OpenHarmony设备接口设计规范
## 总览
硬件设备接口(以下简称为设备接口)作为连通驱动程序和系统服务进行数据流通的桥梁,直接影响着系统的高效性、稳定性、兼容性、可靠性以及数据的正确性、完整性。本文档的目的是规范OpenHarmony设备接口的设计和开发,保证接口的风格一致、功能完备,提升设备接口的设计质量。
本章程由[Driver SIG](https://gitee.com/openharmony/community/blob/master/sig/sig-driver/sig_driver_cn.md)制定,经[PMC](https://gitee.com/link?target=https%3A%2F%2Fwww.openharmony.cn%2Fcommunity%2Fpmc%2F)批准发布;对本章程的修订必须经由Driver SIG评审后,由PMC批准发布。
**术语和定义:**
| 术语 | 缩略语 | 中文解释 |
| --- | ------------------------------ | ------ |
| HDI | Hardware Device Interface | 硬件设备接口 |
| IDL | Interface Description Language | 接口描述语言 |
**用词约定:**
规则:必须遵守的约定
建议:需要加以考虑的约定
说明:对此规则或建议进行相应的解释
**文档变更说明:**
| 版本 | 变更说明 |
| --- | --------------------- |
| v1.0 Beta | 初始试行版本 |
## 范围与定义
![](https://gitee.com/openharmony/docs/raw/master/zh-cn/design/figures/API-Category.png)
硬件设备接口(HDI)如上图所示,位于基础系统服务层和设备驱动层之间,是提供给硬件系统服务开发者使用的、统一的硬件设备功能抽象接口,其目的是为系统服务屏蔽南向设备差异。
## 通用规则
### 接口版本控制
设备接口版本号采用“major.minor”点分格式进行定义,major和minor版本号都应该是整数编号, 其中minor为1位整数,major可以依次递增:
- major代表架构调整或不兼容的接口定义,更新意味着新版本的接口包不向后兼容旧接口包。
- minor代表兼容的接口定义(增强或扩展),更新意味着新版本的接口包向后兼容旧接口包。
major版本号变化时, minor版本号重置为 0。
【举例说明】
对于已发布的vibrator相关接口:
```cpp
package ohos.hdi.vibrator.v1_0;
interface IVibrator {
...
SetModulationParameter([in] unsigned int vibrationPeriod, [in] int intensity, [in] int frequency);
...
}
```
当对原有接口进行不破坏向后兼容的修改时,如在最后追加新增接口、新增枚举定义、修改变量名称等,只需要增加`minor`版本号,新的包名为`ohos.hdi.vibrator.v1_1`。如:
```cpp
package ohos.hdi.vibrator.v1_0;
interface IVibrator {
...
SetModulationParameter([in] unsigned int vibrationPeriod, [in] int intensity, [in] int freq);
...
}
```
如果对原有接口进行更名、修改变量列表等不向后兼容修改时,需要增加`major`版本号,新的包名为`ohos.hdi.vibrator.v2_0`。如:
```cpp
package ohos.hdi.vibrator.v1_0;
interface IVibrator {
...
SetModulationParameter([in] unsigned int vibrationPeriod, [in] int intensity, [in] int frequency, [int] time);
...
}
```
### 接口评审与管控
设备接口主要来源于上层系统服务业务的需求、 以及硬件操作本身具备的属性操作需求,如初始化动作等。新增接口需要充分考虑,该接口的适用范围,不通用的接口会使接口变得十分臃肿,而且增加了维护的难度,因此接口新增和变更必须经过严格的管控。
Table 1 接口评审&管控角色
| **涉及角色** | **API治理中的职责** |
| ----------- | ------------------------------------------------ |
| Contributor | API的设计和交付主体,负责API相关的代码与设计文档提交。 |
| Committer | API相关的代码评审,涉及API提交预审。 |
| 领域SIG | 新增API相关的代码提交评审,领域SIG评审通过即可合入。<br>变更API相关的代码提交预审。 |
| Driver SIG | 变更API相关的代码提交评审。 |
| PMC | API Version计划发布、API治理章程修订评审发布等。 |
#### 设备接口发布
- 接口评审流程
![](figures/HDI-Review-Process.png)
主要过程说明:
1. HDI评审申请、代码提交(Owner:Contributor),所有涉及HDI新增或变更需同步提交相应的API评审文档,详细说明API的需求来源、场景与使用方法、权限设计、隐私保护澄清等,详见后面的API评审申请要素。为避免后续的返工,Contributor可以在正式的API评审申请、代码提交之前,先通过邮件方式将API设计文档提交Committer、领域SIG、API SIG等相关人员预审。
2. 代码评审(Owner:Committer),代码评审和API预审,涉及API提交Code Review通过后,还需要进一步领域SIG评审。
3. 领域SIG评审(Owner:领域SIG),涉及新增/变更HDI相关接口的代码提交,领域SIG评审通过后,还需要进一步提交Driver SIG。
4. HDI评审(Owner:Driver SIG),对新增/变更HDI相关的代码提交进行接口评审,评审通过即可合入代码。
5. 评审完成。
- 评审要素
接口设计完成以后,需经领域SIG组织有效的评审,并提供相应的配套资料,发布前需提供:
- 提供完善的用例,确保用例的合理性和完备性。
- **提供接口版本差异报告,明确接口新增或者变更范围**。
- 需要在设计文档中提供完整的接口上下文,明确接口的使用范围和方法。
- 在设计面向资源性的接口时,需要在设计文档中提供相应的资源状态迁移图。
- 本文档中提出的接口设计约束的遵从性。
- 规范要求
1. **当接口变更存在不兼容时,需要变更“major”版本号;**
2. **“功能扩展”接口发布时需要修改“minor”版本号。**
3. 针对废弃已发布设备接口,本规范要求:
- 对废弃接口增加标识废弃标记。
- 废弃API至少保留4个OpenHarmony API版本
## 接口设计约束
### 一致性要求
#### 【规则】业务术语必须采用统一名词
相应的业务术语必须采用统一名词,不允许使用多个语意接近的名词表示同一个业务对象;同样地,为了避免产生混淆,也不允许针对不同的业务对象使用相同的名词或语言接近的名词。
#### 【规则】接口参数顺序必须一致性
相同参数/参数序列在多个接口中的位置和顺序保持一致。
对于C面向对象编程时,对象方法接口按照惯例应该放到第一个参数。
#### 【规则】内存所有权必须保持一致
在设计设备接口时,通过入参(in)或出参(out)传递的内存(存储数据),如果由调用者申请,则必须由调用者释放,如果由被调用者申请,则必须由被调用者释放,从而避免因为内存所有权混乱导致的内存释放类问题。无论是将数据由服务传递到驱动中,还是从驱动中接收数据,都不能改变数据的所有权,也就是说数据所有权始终属于内存数据申请者;
【举例说明】
```cpp
int (*OpenLayer)(uint32_t devId, const LayerInfo *layerInfo, uint32_t *layerId);
```
在调用OpenLayer接口时,根据入参layerInfo创建图层数据内存,并返回layerId
```cpp
int (*CloseLayer)(uint32_t devId, uint32_t layerId);
```
对应以上OpenLayer接口,必须提供CloseLayer接口;
这样,在调用者业务操作结束后,可以调用该接口关闭被调用者创建的图层数据内存;
#### 【规则】同步接口必须有明确的返回值
定义同步接口必须明确指定返回值,可以提供必要的接口调用状态信息。调用是否成功?如果接口调用失败了,那么失败的原因是什么,即使有些看似必然会成功的接口。返回值定义,根据实际的错误原因可以自行定义,本规范不做强制要求。
【例外说明】
如果某个接口属于单向方法,即调用该接口后不用等待该接口执行即可返回,在注解中使用关键字“one way”进行修饰。示例:
```cpp
/* one way */
void WriteReady();
```
### 命名要求
#### 【规则】接口命名使用‘I’+“接口名“的格式
接口命名应当简洁、易懂、准确,避免冗余、误导性、不通用的缩写等降低可读性的表达。
【举例说明】
```
/* good */
interface IBattery {
...
}
/* bad: Interface后缀与I前缀重复 */
interface IBatteryInterface {
...
}
```
#### 【规则】接口包名使用“package ohos.hdi.[接口名].v[major_version]_[minor_version]”格式
【举例说明】
```
/* good */
package ohos.hdi.battery.v1_0;
interface IBattery {
...
}
/* bad: 缺少hdi命名空间与version信息 */
package ohos.battery;
interface IBattery {
...
}
```
#### 【规则】类、结构体、接口方法、参数等采用驼峰命名风格
__驼峰风格(CamelCase)__
大小写字母混用,单词连在一起,不同单词间通过单词首字母大写来分开。
按连接后的首字母是否大写,又分: 大驼峰(UpperCamelCase)和小驼峰(lowerCamelCase)
| 类型 | 命名风格 |
| ---------------------------------------- | --------- |
| 接口类型,接口方法,结构体类型,枚举类型,联合体类型等类型定义 | 大驼峰 |
| 函数参数,结构体和联合体中的成员变量 | 小驼峰 |
| 常量,枚举值 | 全大写,下划线分割 |
#### 【规则】接口文件应与接口类同名且使用'.idl'文件后缀
- 每个接口类应定义在独立的接口文件中,并使文件命名与接口类保持一致(大驼峰命名),并以`.idl`后缀结尾。
- 对于类型定义的描述文件应该命名为`Types.idl`,也可使用有适当前缀的`XxxTypes.idl`风格。
【举例说明】
```
package ohos.hdi.battery.v1_0;
interface IBattery {
...
}
```
以上接口的接口描述文件应该命名为`IBattery.idl`.
### 易用性要求
#### 【规则】接口设计必须遵从单一职责原则
设备接口的功能职责应该是固定的、明确的,引起接口变化触发源是唯一的;
【举例说明】
以更新设备状态为例,设备状态可能包含状态电源状态、端口状态。
**正例:**
```cpp
int UpdatePowerState(int_t deviceId, int status); //该接口只负责更新设备电源状态的职责。
int UpdatePortStatus(int deviceId, int status); // 该接口只负责更新设备端口状态的职责。
```
**反例:**
```cpp
int UpdateDeviceStatus(int deviceId, int powerStatus, int portStatus);
```
#### 【规则】接口参数设计时必须考虑内聚性
在定义一个接口参数时,需要考虑是单独传递参数还是将参数封装在结构体中传递,在做选择时,需要权衡以下几个因素:
1. 是否存在有意义的封装边界?
如果参数间存在明显的内聚性或者关联,那么可以将这些参数封装在一个结构体中。
2. 如果采用结构化参数传递时,该结构是否还有其他用处?
如果没有,可考虑单独传递参数;
3. 是否在多个接口中重复相同的参数组?
如果是,可以考虑将这些参数组成一个结构进行传递;当然,也需要考虑这些重复使用的参数组是否有内聚性;
4. 是否有大量的参数是可选的,或者通常会给一个默认值?
如果是,可以考虑使用结构体来简化接口调用者的使用;
【举例说明】
音频采样属性包括采样格式、采样频率、通道数等,属于采样相关的参数性质,可考虑结构化传递。
```cpp
struct AudioSampleAttributes
{
    enum AudioFormat format;
    uint32_t sampleRate;
    uint32_t channelCount;
};
```
#### 【规则】不同类别接口间不能相互依赖
设备接口以驱动类别如`Camera`, `Input`, `Display`, `Audio`, `Sensor`, `Storage`等为粒度进行管理。要求不同类别设备接口不能出现相互依赖场景。针对超过两个类别驱动模块都可能使用的通用能力,建议抽象成通用接口,统一归档到通用接口能力库进行管理。
【例外场景】
对于公共能力的接口部分不做约束,如:基础类型的定义和接口的声明部分,可以被所有接口引用。
### 隐私保护要求
### 【规则】接口必须考虑隐私安全
在系统服务通过驱动中经常可以访问到设备信息和标识等数据,部分信息如设备名称、序列号、设备地址等属于隐私保护规范中的敏感数据,在接口设计时,需要特别注意这些类型字段的使用,需要仔细、彻底的审查,确保设计的接口无超出信息。
【举例说明】
`Bluetooth`地址主要用于设备发现和连接,当设备处于可发现状态时,`Bluetooth`的地址可能被用于个人跟踪;
对于调用者获取`Bluetooth`设备地址的目的主要用于唯一标识设备,基于这个考虑可将`Bluetooth`设备进行唯一标识转换提供给用户使用,或者限制该接口的使用范围。
### 权限控制要求
#### 【规则】接口权限需要遵循最小开放原则
一切穿透沙箱的行为都需考虑使用权限来管控,一个权限仅对确有正当业务需求的应用开放。
### 性能要求
#### 【规则】必须考虑传输效率
驱动存在大量数据传输接口。在数据传输过程中可能需要跨进程,这意味着系统开销,可能会触发系统调度等,过多的数据量对传输的压力非常大。所以在接口定义时,需要综合考虑各种情况进行设计,对于必须在开销较小且实时性要求高的进程间传输数据时,可以使用共享内存、消息队列等;
【举例说明】
在某个驱动模块设计数据传输接口时,接口定义如下:
```cpp
// 不涉及跨进程通信(接口直调)
int WriteData(); // 这里入参直接定义为数据的地址指针和数据长度
/*
* 涉及跨进程通信(涉及IPC远程调用)
*
* 这里入参是共享内存或消息队列的对象
* 通过这种方式实现数据的高效传输(尽可能减少复制操作的次数)
*/
int PrepareWriteData();
```
#### 【建议】接口需要考虑执行时间
为了提高IPC的通信性能,当服务端流程业务较长时,建议采用异步处理。如果客户端需要同步等待结果时,建议在客户端中增加阻塞,等待异步回调返回方式实现,以便于及时释放IPC通道。
【举例说明】
Camera提供了设备初始化的设备接口,但是该接口因为软硬件的原因耗时较长(>150ms),如果该接口为同步方式,可能较长时间占用Camera HDI
Service IPC线程,造成其他请求不能及时响应。故该接口设计为异步调用更为合理,如果客户端需要获得初始化结果,可以使用回调的方式获得。客户端流程如需等待初始化接口返回再继续执行,可以在客户端阻塞等待回调结果。
#### 【建议】尽可能减少新增进程实体
为了降低系统开销,对于同一子系统、同类型的接口,应当部署到同一进程中,无切实必要不新增进程。
### 功耗要求
#### 【规则】接口设计需要考虑对系统功耗的影响
当调用者释放对硬件资源的访问时,相应驱动模块应释放对系统唤醒锁的持有,避免阻塞系统休眠。
### 可靠性要求
#### 【规则】接口参数禁止生命周期相互依赖
接口参数的生命周期必须是独立的,应禁止相互依赖,不能出现指针参数指向其他对象的内存,比较典型的是出现指针参数指向本序列化内存块的场景,因为当序列化内存传递到对端函数处理时,它的生命周期会随着参数解析完成而消亡,而指针可能在不同函数间传递,容易出现UAF(Used After Free)等稳定性问题。
【举例说明】
反序列化接口ReadUnpadBuffer和ReadCString均返回一个指针变量,该指针指向序列化对象内部内存,当服务端响应回调返回后,用于传递参数的序列化对象将被销毁,同时内存也被释放。如果服务端其他流程还在使用上述两个接口返回的指针,很可能因为UAF而出现crash等问题。
正确做法是如果需要在服务响应接口返回后继续使用数据,应将数据拷贝到自己管理的内存中再使用。
#### 【规则】必须考虑可重入性
设备接口往往需要支持多客户端,单一客户端也可能存在并发请求,所以接口设计时必须考虑可重入。为了保证接口重入的正确处理,对于存在竞争的资源应该使用锁/信号量等妥善保护。
【举例说明】
某驱动服务提供了资源请求/释放接口,当两个客户端同时请求资源时,如果服务端资源管理临界资源未考虑重入,可能导致资源管理数据读写竞争出现提前释放/不能释放等问题。正确做法应该为临界资源加锁保护。
#### 【建议】需要考虑传输缓冲能力
本规范不强制限制在接口或回调接口中发送的数据量(流量控制),如果出现传输超过通信最大缓冲能力的调用情况时,建议重新设计给定的设备接口。在设计接口时,如果超过通信缓冲能力限制的调用时,应考虑增加阻塞等方式直到资源可用。
【举例说明】
当内存申请失败时,通过信号量等待方式阻塞当前线程,直到内存可用返回。
#### 【规则】禁止跨地址空间传递函数指针
进程间存在虚拟地址空间隔离,通过IPC传递函数指针必然会导致访问异常,所以禁止传递函数指针。如果需要实现回调函数功能,请使用回调对象替代。
【举例说明】
Wi-Fi模块提供接口要在客户端接受服务端的回调,错误做法是将客户端实现的函数指针直接写入序列化对象,这样会在服务端调用该函数指针时发生crash等问题。
正确做法是基于回调对象设计并实现回调接口,将回调对象通过序列化接口传递给服务端,服务端在需要的时候可以回调。
### 兼容性要求
#### 【规则】客户端调用设备接口前,必须校验版本号
因为组件独立升级策略,客户端和服务端接口版本号可能存在不一致,客户端在调用设备接口之前必须先校验服务端实际版本号并使用与之匹配的客户端接口版本进行调用。
【举例说明】
假设TP模块存在1.0和1.1等版本接口,其中1.1扩展了1.0接口,新增了接口。因为组件独立升级,适配了1.1接口的系统组件可能先升级,服务端在芯片组件未升级还是1.0实现。如果在客户端使用1.1接口直接调用服务端尚不支持的接口,可能会导致调用错误,影响功能实现。所以在调用前应先使用服务版本查询接口先确认服务端版本号,如果服务端是1.0版本则使用1.0版本客户端接口调用。
#### 【规则】设备接口必须以IDL形式对外发布
目前类Unix体系的驱动采用VFS接口形式对外暴露接口,用户态和内核态采用System Call方式进行通信,由于分别打包在不同镜像中,因此需要单独维护两套接口。为了保持二者之间的接口定义和参数形式的一致性,同时也考虑HDF跨内核部署这个设计目标,因此建议设备接口通过IDL形式发布,通过工具根据目标形态生成目标形态的接口形式。同时也禁止用户态调用者直接通过文件接口操作驱动VFS接口,因为这样会引入Framework对内核的强依赖,也违背了依赖接口而不依赖实现的原则。
建议的做法:驱动提供IDL服务接口,在设备接口实现中封装对内核设备的访问。
【举例说明】
输入设备需要对外提供属性查询的功能,如设备类型、数据精度等信息,输入服务不应该直接通过open-IOCtl的方式直接访问内核创建的VFS设备接口,输入驱动应该提供设备接口,将输入设备抽象为对象,输入服务调用输入设备对象的接口实现相应功能。
### 文档化要求
#### 【规则】设备接口必须以IDL形式发布
为了保证接口的兼容性与一致性,必须以IDL形式发布设备接口,禁止通过C/C++头文件的形式直接发布接口。
#### 【规则】接口发布时必须提供接口说明
接口说明应该包含接口的功能、参数的取值范围、返回的结果、注意事项等信息,接口说明文本应该在接口idl文件中的接口描述的上方,随着接口一起发布。
【举例说明】
```
/**
* @brief Get executor info.
*
* @param executorInfo Indicates executor info, see {@link ExecutorInfo}.
*
* @return Returns <b>0</b> if the operation is successful.
* @return Returns a non-zero value if the operation fails.
*/
GetExecutorInfo([out] struct ExecutorInfo executorInfo);
```
### 编程语言要求
为了保证不同语言实现的设备接口数据互通,设备接口描述中的基本数据类型需要严格按照下表对应。
#### 基础类型使用约束
| IDL基本数据类型 | C++数据类型 | C数据类型 | 数据长度(bytes) |
| -------------- | ----------- | --------------- | ----------- |
| void | void | void | NA |
| boolean | bool | bool | 1 |
| byte | int8_t | int8_t | 1 |
| short | int16_t | int16_t | 2 |
| int | int32_t | int32_t | 4 |
| long | int64_t | int64_t | 8 |
| float | float | float | 4 |
| double | double | double | 8 |
| String | std::string | char*, int size | NA |
| unsigned char | uint8_t | uint8_t | 1 |
| unsigned short | uint16_t | uint16_t | 2 |
| unsigned int | uint32_t | uint32_t | 4 |
| unsigned long | uint64_t | uint64_t | 8 |
#### 容器类型使用约束
| IDL容器数据类型 | C++数据类型 | C数据类型 |
| ----------- | ------------ | ----------- |
| List<T> | std::list<T> | T*,int size |
#### 数组类型使用约束
| IDL容器数据类型 | C++数据类型 | C数据类型 |
| --------- | -------------- | ----------- |
| T[] | std::vector<T> | T*,int size |
#### 自定义类型使用约束
| IDL数据类型 | C++数据类型 | C数据类型 |
| ------- | ------- | ------ |
| struct | struct | struct |
| enum | enum | enum |
## 其他说明
本文档Beta期为自发布日起1个月,用于接纳社区意见,欢迎积极参与讨论。
\ No newline at end of file
...@@ -32,16 +32,16 @@ OpenHarmony也提供了一系列可选的系统组件,方便设备开发者按 ...@@ -32,16 +32,16 @@ OpenHarmony也提供了一系列可选的系统组件,方便设备开发者按
**表 1** 轻量和小型系统开发指导(参考内存<128MiB) **表 1** 轻量和小型系统开发指导(参考内存<128MiB)
| 学习路径 | 开发者业务 | 相关文档 | | 学习路径 | 开发者业务 | 相关文档 |
| -------- | -------- | -------- | | --------------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
| 了解OpenHarmony | 整体认知OpenHarmony | -&nbsp;[OpenHarmony概述](https://gitee.com/openharmony)<br/>-&nbsp;[术语](../glossary.md) | | 了解OpenHarmony | 整体认知OpenHarmony | -&nbsp;[OpenHarmony概述](https://gitee.com/openharmony)<br/>-&nbsp;[术语](../glossary.md) |
| 获取开发资源 | 准备开发前相关资源 | -&nbsp;[获取源码](get-code/sourcecode-acquire.md)<br/>-&nbsp;[获取工具](get-code/gettools-acquire.md) | | 获取开发资源 | 准备开发前相关资源 | -&nbsp;[获取源码](get-code/sourcecode-acquire.md)<br/>-&nbsp;[获取工具](get-code/gettools-acquire.md) |
| 快速入门 | 快速熟悉OpenHarmony环境搭建、编译、烧录、调测、运行 | -&nbsp;[轻量和小型系统快速入门](quick-start/quickstart-ide-lite-overview.md) | | 快速入门 | 快速熟悉OpenHarmony环境搭建、编译、烧录、调测、运行 | -&nbsp;[轻量和小型系统快速入门](quick-start/quickstart-ide-lite-overview.md) |
| 基础能力使用 | 使用OpenHarmony提供的基础能力 | -&nbsp;[轻量系统内核开发指南](kernel/kernel-mini-overview.md)<br/>-&nbsp;[小型系统内核开发指南](kernel/kernel-small-overview.md)<br/>-&nbsp;[驱动开发指南](driver/driver-hdf-overview.md)<br/>-&nbsp;[子系统开发指南](subsystems/subsys-build-mini-lite.md)<br/>-&nbsp;[安全指南](security/security-guidelines-overall.md)<br/>-&nbsp;[隐私保护](security/security-privacy-protection.md) | | 基础能力使用 | 使用OpenHarmony提供的基础能力 | -&nbsp;[轻量系统内核开发指南](kernel/kernel-mini-overview.md)<br/>-&nbsp;[小型系统内核开发指南](kernel/kernel-small-overview.md)<br/>-&nbsp;[驱动开发指南](driver/driver-hdf-overview.md)<br/>-&nbsp;[子系统开发指南](subsystems/subsys-build-mini-lite.md)<br/>-&nbsp;[安全指南](security/security-guidelines-overall.md)<br/>-&nbsp;[隐私保护](security/security-privacy-protection.md) |
| 进阶开发 | 结合系统能力开发智能设备 | -&nbsp;[WLAN连接类产品](guide/device-wlan-led-control.md)<br/>-&nbsp;[无屏摄像头类产品](guide/device-iotcamera-control-overview.md)<br/>-&nbsp;[带屏摄像头类产品](guide/device-camera-control-overview.md) | | 进阶开发 | 结合系统能力开发智能设备 | -&nbsp;[WLAN连接类产品](guide/device-wlan-led-control.md)<br/>-&nbsp;[无屏摄像头类产品](guide/device-iotcamera-control-overview.md)<br/>-&nbsp;[带屏摄像头类产品](guide/device-camera-control-overview.md) |
| 移植适配 | -&nbsp;针对特定芯片做移植适配<br/>-&nbsp;对三方库进行移植适配 | -&nbsp;[轻量系统芯片移植指导](porting/porting-minichip.md)<br/>-&nbsp;[小型系统芯片移植指导](porting/porting-smallchip-prepare-needs.md)<br/>-&nbsp;[轻量和小型系统三方库移植指导](porting/porting-thirdparty-overview.md) | | 移植适配 | -&nbsp;针对特定芯片做移植适配<br/>-&nbsp;对三方库进行移植适配<br/>-&nbsp;三方厂商移植案例<br/> | -&nbsp;[轻量系统芯片移植指导](porting/porting-minichip.md)<br/>-&nbsp;[小型系统芯片移植指导](porting/porting-smallchip-prepare-needs.md)<br/>-&nbsp;[轻量和小型系统三方库移植指导](porting/porting-thirdparty-overview.md)<br/> - [带屏解决方案之恒玄芯片移植案例](porting-bes2600w-on-minisystem-display-demo.md)<br/> - [Combo解决方案之ASR芯片移植案例](porting-asr582x-combo-demo.md)<br/> - [物联网解决方案之芯海cst85芯片移植案例](porting-cst85f01-combo-demo.md)<br/> - [轻量系统STM32F407芯片移植案例](porting-stm32f407-on-minisystem-eth.md)<br/> - [Combo解决方案之W800芯片移植案例](porting-w800-combo-demo.md)<br/> - [小型设备STM32MP1芯片移植案例](porting-stm32mp15xx-on-smallsystem.md)|
| 贡献组件 | 为OpenHarmony贡献功能组件 | -&nbsp;[HPM&nbsp;Part&nbsp;介绍](hpm-part/hpm-part-about.md)<br/>-&nbsp;[HPM&nbsp;Part&nbsp;开发指导](hpm-part/hpm-part-development.md)<br/>-&nbsp;[HPM&nbsp;Part&nbsp;参考](hpm-part/hpm-part-reference.md) | | 贡献组件 | 为OpenHarmony贡献功能组件 | -&nbsp;[HPM&nbsp;Part&nbsp;介绍](hpm-part/hpm-part-about.md)<br/>-&nbsp;[HPM&nbsp;Part&nbsp;开发指导](hpm-part/hpm-part-development.md)<br/>-&nbsp;[HPM&nbsp;Part&nbsp;参考](hpm-part/hpm-part-reference.md) |
| 参考 | 开发参考 | [常见问题](faqs/faqs-overview.md) | | 参考 | 开发参考 | [常见问题](faqs/faqs-overview.md)
**表 2** 标准系统开发指导(参考内存≥128MiB) **表 2** 标准系统开发指导(参考内存≥128MiB)
...@@ -52,6 +52,6 @@ OpenHarmony也提供了一系列可选的系统组件,方便设备开发者按 ...@@ -52,6 +52,6 @@ OpenHarmony也提供了一系列可选的系统组件,方便设备开发者按
| 快速入门 | 快速熟悉OpenHarmony环境搭建、编译、烧录、调测、运行 | -&nbsp;[标准系统快速入门](quick-start/quickstart-ide-standard-overview.md) | | 快速入门 | 快速熟悉OpenHarmony环境搭建、编译、烧录、调测、运行 | -&nbsp;[标准系统快速入门](quick-start/quickstart-ide-standard-overview.md) |
| 基础能力使用 | 使用OpenHarmony提供的基础能力 | -&nbsp;[内核开发指南](kernel/kernel-standard.md)<br/>-&nbsp;[驱动开发指南](driver/driver-hdf-overview.md)<br/>-&nbsp;[子系统开发指南](subsystems/subsys-build-standard-large.md)<br/>-&nbsp;[安全指南](security/security-guidelines-overall.md)<br/>-&nbsp;[隐私保护](security/security-privacy-protection.md) | | 基础能力使用 | 使用OpenHarmony提供的基础能力 | -&nbsp;[内核开发指南](kernel/kernel-standard.md)<br/>-&nbsp;[驱动开发指南](driver/driver-hdf-overview.md)<br/>-&nbsp;[子系统开发指南](subsystems/subsys-build-standard-large.md)<br/>-&nbsp;[安全指南](security/security-guidelines-overall.md)<br/>-&nbsp;[隐私保护](security/security-privacy-protection.md) |
| 进阶开发 | 结合系统能力开发智能设备 | -&nbsp;[时钟应用开发指导](guide/device-clock-guide.md)<br/>-&nbsp;[平台驱动开发示例](guide/device-driver-demo.md)<br/>-&nbsp;[外设驱动开发示例](guide/device-outerdriver-demo.md) | | 进阶开发 | 结合系统能力开发智能设备 | -&nbsp;[时钟应用开发指导](guide/device-clock-guide.md)<br/>-&nbsp;[平台驱动开发示例](guide/device-driver-demo.md)<br/>-&nbsp;[外设驱动开发示例](guide/device-outerdriver-demo.md) |
| 移植适配 | 对三方库进行移植适配 | -&nbsp;[标准系统芯片移植指导](porting/standard-system-porting-guide.md)<br/>-&nbsp;[一种快速移植OpenHarmony&nbsp;Linux内核的方法](porting/porting-linux-kernel.md) | | 移植适配 | -&nbsp;针对特定芯片做移植适配 <br/>-&nbsp;快速移植OpenHarmony&nbsp;Linux内核的方法| -&nbsp;[标准系统芯片移植指导](porting/standard-system-porting-guide.md)<br/>-&nbsp;[一种快速移植OpenHarmony&nbsp;Linux内核的方法](porting/porting-linux-kernel.md) |
| 贡献组件 | 为OpenHarmony贡献功能组件 | -&nbsp;[HPM&nbsp;Part&nbsp;介绍](hpm-part/hpm-part-about.md)<br/>-&nbsp;[HPM&nbsp;Part&nbsp;开发指导](hpm-part/hpm-part-development.md)<br/>-&nbsp;[HPM&nbsp;Part&nbsp;参考](hpm-part/hpm-part-reference.md) | | 贡献组件 | 为OpenHarmony贡献功能组件 | -&nbsp;[HPM&nbsp;Part&nbsp;介绍](hpm-part/hpm-part-about.md)<br/>-&nbsp;[HPM&nbsp;Part&nbsp;开发指导](hpm-part/hpm-part-development.md)<br/>-&nbsp;[HPM&nbsp;Part&nbsp;参考](hpm-part/hpm-part-reference.md) |
| 参考 | 开发参考 | [常见问题](faqs/faqs-overview.md) | | 参考 | 开发参考 | [常见问题](faqs/faqs-overview.md) |
...@@ -16,7 +16,7 @@ Audio驱动框架基于[HDF驱动框架](https://device.harmonyos.com/cn/docs/do ...@@ -16,7 +16,7 @@ Audio驱动框架基于[HDF驱动框架](https://device.harmonyos.com/cn/docs/do
![](figures/Audio框架图.png) ![](figures/Audio框架图.png)
驱动架构主要由以下几部分组成。 驱动架构主要由以下几部分组成。
- HDI adapter: 实现Audio HAL层驱动(HDI接口适配),给Audio服务(frameworks)提供所需的音频硬件驱动能力接口。包含 Audio Manager、Audio Adapter、Audio Control、Audio Capture、Audio Render等接口对象。 - HDI adapter:实现Audio HAL层驱动(HDI接口适配),给Audio服务(frameworks)提供所需的音频硬件驱动能力接口。包含 Audio Manager、Audio Adapter、Audio Control、Audio Capture、Audio Render等接口对象。
- Audio Interface Lib:配合内核中的Audio Driver Model使用,实现音频硬件的控制、录音数据的读取、播放数据的写入。它里面包括Stream_ctrl_common 通用层,主要是为了和上层的audio HDI adapter层进行对接。 - Audio Interface Lib:配合内核中的Audio Driver Model使用,实现音频硬件的控制、录音数据的读取、播放数据的写入。它里面包括Stream_ctrl_common 通用层,主要是为了和上层的audio HDI adapter层进行对接。
- ADM(Audio Driver Model):音频驱动框架模型,向上服务于多媒体音频子系统,便于系统开发者能够更便捷的根据场景来开发应用。向下服务于具体的设备厂商,对于Codec和DSP设备厂商来说,可根据ADM模块提供的向下统一接口适配各自的驱动代码,就可以实现快速开发和适配OpenHarmony系统。 - ADM(Audio Driver Model):音频驱动框架模型,向上服务于多媒体音频子系统,便于系统开发者能够更便捷的根据场景来开发应用。向下服务于具体的设备厂商,对于Codec和DSP设备厂商来说,可根据ADM模块提供的向下统一接口适配各自的驱动代码,就可以实现快速开发和适配OpenHarmony系统。
- Audio Control Dispatch: 接收lib层的控制指令并将控制指令分发到驱动层。 - Audio Control Dispatch: 接收lib层的控制指令并将控制指令分发到驱动层。
......
...@@ -77,7 +77,6 @@ OpenHarmony WLAN模组基于Hi3861平台提供了丰富的外设操作能力, ...@@ -77,7 +77,6 @@ OpenHarmony WLAN模组基于Hi3861平台提供了丰富的外设操作能力,
break; break;
} }
} }
return NULL;
} }
``` ```
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
## 简介 ## 简介
OpenHarmony 轻量级内核是基于IoT领域轻量级物联网操作系统Huawei LiteOS内核演进发展的新一代内核,包含LiteOS-M和LiteOS-A两类内核。LiteOS-M内核主要应用于轻量系统,面向的MCU(Micro Processor Unit)一般是百K级内存,可支持MPU(Memory Protection Unit)隔离,业界类似的内核有FreeRTOS或ThreadX等;LiteOS-A内核主要应用于小型系统,面向设备一般是M级内存,可支持MMU(Memory Management Unit)隔离,业界类似的内核有Zircon或Darwin等。 OpenHarmony 轻量级内核是基于IoT领域轻量级物联网操作系统Huawei LiteOS内核演进发展的新一代内核,包含LiteOS-M和LiteOS-A两类内核。LiteOS-M内核主要应用于轻量系统,面向的MCU(Microprocessor Unit)一般是百K级内存,可支持MPU(Memory Protection Unit)隔离,业界类似的内核有FreeRTOS或ThreadX等;LiteOS-A内核主要应用于小型系统,面向设备一般是M级内存,可支持MMU(Memory Management Unit)隔离,业界类似的内核有Zircon或Darwin等。
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> OpenHarmony针对不同量级的系统,分别使用了不同形态的内核,小型系统支持LiteOS和Linux,本开发指南适用于LiteOS-A内核,linux内核的相关操作请参考[Linux内核概述](../kernel/kernel-standard-overview.md)。 > OpenHarmony针对不同量级的系统,分别使用了不同形态的内核,小型系统支持LiteOS和Linux,本开发指南适用于LiteOS-A内核,linux内核的相关操作请参考[Linux内核概述](../kernel/kernel-standard-overview.md)。
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册