未验证 提交 237c679c 编写于 作者: O openharmony_ci 提交者: Gitee

!10820 翻译已完成9237+9642+8860+9861+9917+9921+9903+9865+9837+9838+9796+9778+9764

Merge pull request !10820 from shawn_he/9237-a
...@@ -12,7 +12,7 @@ To use related APIs, you must declare the **ohos.permission.INTERNET** permissio ...@@ -12,7 +12,7 @@ To use related APIs, you must declare the **ohos.permission.INTERNET** permissio
For details about how to apply for permissions, see [Access Control Development](../security/accesstoken-guidelines.md). For details about how to apply for permissions, see [Access Control Development](../security/accesstoken-guidelines.md).
The following table describes the related APIs. The following table provides only a simple description of the related APIs. For details, see [API Reference](../reference/apis/js-apis-http.md).
| API | Description | | API | Description |
| ----------------------------------------- | --------------------------------------------------------- | | ----------------------------------------- | --------------------------------------------------------- |
......
...@@ -15,15 +15,18 @@ Your application can call location-specific APIs to obtain the location informat ...@@ -15,15 +15,18 @@ Your application can call location-specific APIs to obtain the location informat
Location awareness helps determine where a mobile device locates. The system identifies the location of a mobile device with its coordinates, and uses location technologies such as Global Navigation Satellite System (GNSS) and network positioning (for example, base station positioning or WLAN/Bluetooth positioning) to provide diverse location-based services. These advanced location technologies make it possible to obtain the accurate location of the mobile device, regardless of whether it is indoors or outdoors. Location awareness helps determine where a mobile device locates. The system identifies the location of a mobile device with its coordinates, and uses location technologies such as Global Navigation Satellite System (GNSS) and network positioning (for example, base station positioning or WLAN/Bluetooth positioning) to provide diverse location-based services. These advanced location technologies make it possible to obtain the accurate location of the mobile device, regardless of whether it is indoors or outdoors.
- **Coordinate** - **Coordinate**
A coordinate describes a location on the earth using the longitude and latitude in reference to the World Geodetic Coordinate System 1984. A coordinate describes a location on the earth using the longitude and latitude in reference to the World Geodetic Coordinate System 1984.
- **GNSS positioning** - **GNSS positioning**
GNSS positioning locates a mobile device by using the location algorithm offered by the device chip to compute the location information provided by the Global Navigation Satellite System, for example, GPS, GLONASS, BeiDou, and Galileo. Whichever positioning system will be used during the location process depends on a hardware capability of the device. GNSS positioning locates a mobile device by using the location algorithm offered by the device chip to compute the location information provided by the Global Navigation Satellite System, for example, GPS, GLONASS, BeiDou, and Galileo. Whichever positioning system will be used during the location process depends on a hardware capability of the device.
- **Base station positioning** - **Base station positioning**
Base station positioning estimates the current location of a mobile device based on the location of the resident base station in reference to the neighboring base stations. This technology provides only a low accuracy and requires access to the cellular network. Base station positioning estimates the current location of a mobile device based on the location of the resident base station in reference to the neighboring base stations. This technology provides only a low accuracy and requires access to the cellular network.
- **WLAN or Bluetooth positioning** - **WLAN or Bluetooth positioning**
WLAN or Bluetooth positioning estimates the current location of a mobile device based on the locations of WLANs and Bluetooth devices that can be discovered by the device. The location accuracy of this technology depends on the distribution of fixed WLAN access points (APs) and Bluetooth devices around the device. A high density of WLAN APs and Bluetooth devices can produce a more accurate location result than base station positioning. This technology also requires access to the network. WLAN or Bluetooth positioning estimates the current location of a mobile device based on the locations of WLANs and Bluetooth devices that can be discovered by the device. The location accuracy of this technology depends on the distribution of fixed WLAN access points (APs) and Bluetooth devices around the device. A high density of WLAN APs and Bluetooth devices can produce a more accurate location result than base station positioning. This technology also requires access to the network.
......
...@@ -38,7 +38,7 @@ You can set a USB device as the USB host to connect to other USB devices for dat ...@@ -38,7 +38,7 @@ You can set a USB device as the USB host to connect to other USB devices for dat
// Import the USB API package. // Import the USB API package.
import usb from '@ohos.usb'; import usb from '@ohos.usb';
// Obtain the USB device list. // Obtain the USB device list.
var deviceList = usb.getDevices(); let deviceList = usb.getDevices();
/* /*
Example deviceList structure Example deviceList structure
[ [
...@@ -81,21 +81,21 @@ You can set a USB device as the USB host to connect to other USB devices for dat ...@@ -81,21 +81,21 @@ You can set a USB device as the USB host to connect to other USB devices for dat
number: 1, number: 1,
type: 3, type: 3,
interfaceId: 0, interfaceId: 0,
}, }
], ]
}, }
], ]
}, }
], ]
}, }
], ]
*/ */
``` ```
2. Obtain the device operation permissions. 2. Obtain the device operation permissions.
```js ```js
var deviceName = deviceList[0].name; let deviceName = deviceList[0].name;
// Request the permissions to operate a specified device. // Request the permissions to operate a specified device.
usb.requestRight(deviceName).then(hasRight => { usb.requestRight(deviceName).then(hasRight => {
console.info("usb device request right result: " + hasRight); console.info("usb device request right result: " + hasRight);
...@@ -108,7 +108,7 @@ You can set a USB device as the USB host to connect to other USB devices for dat ...@@ -108,7 +108,7 @@ You can set a USB device as the USB host to connect to other USB devices for dat
```js ```js
// Open the device, and obtain the USB device pipe for data transfer. // Open the device, and obtain the USB device pipe for data transfer.
var pipe = usb.connectDevice(deviceList[0]); let pipe = usb.connectDevice(deviceList[0]);
/* /*
Claim the corresponding interface from deviceList. Claim the corresponding interface from deviceList.
interface1 must be one present in the device configuration. interface1 must be one present in the device configuration.
...@@ -127,7 +127,7 @@ You can set a USB device as the USB host to connect to other USB devices for dat ...@@ -127,7 +127,7 @@ You can set a USB device as the USB host to connect to other USB devices for dat
usb.bulkTransfer(pipe, inEndpoint, dataUint8Array, 15000).then(dataLength => { usb.bulkTransfer(pipe, inEndpoint, dataUint8Array, 15000).then(dataLength => {
if (dataLength >= 0) { if (dataLength >= 0) {
console.info("usb readData result Length : " + dataLength); console.info("usb readData result Length : " + dataLength);
var resultStr = this.ab2str(dataUint8Array); // Convert uint8 data into a string. let resultStr = this.ab2str(dataUint8Array); // Convert uint8 data into a string.
console.info("usb readData buffer : " + resultStr); console.info("usb readData buffer : " + resultStr);
} else { } else {
console.info("usb readData failed : " + dataLength); console.info("usb readData failed : " + dataLength);
......
...@@ -19,7 +19,7 @@ Applicable to: OpenHarmony SDK 3.2.2.5, stage model of API version 9 ...@@ -19,7 +19,7 @@ Applicable to: OpenHarmony SDK 3.2.2.5, stage model of API version 9
Applicable to: OpenHarmony SDK 3.2.2.5, stage model of API version 9 Applicable to: OpenHarmony SDK 3.2.2.5, stage model of API version 9
Error code 28 refers to **CURLE_OPERATION_TIMEDOUT**, which means a libcurl library operation timeout. For details, see any HTTP status code description available. Error code 28 refers to **CURLE_OPERATION_TIMEDOUT**, which means a cURL operation timeout. For details, see any HTTP status code description available.
Reference: [Development Guide](https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-http.md#httpresponse) and [Curl Error Codes](https://curl.se/libcurl/c/libcurl-errors.html) Reference: [Development Guide](https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-http.md#httpresponse) and [Curl Error Codes](https://curl.se/libcurl/c/libcurl-errors.html)
......
...@@ -4,5 +4,6 @@ ...@@ -4,5 +4,6 @@
- [Drawing Development](drawing-guidelines.md) - [Drawing Development](drawing-guidelines.md)
- [Raw File Development](rawfile-guidelines.md) - [Raw File Development](rawfile-guidelines.md)
- [Native Window Development](native-window-guidelines.md) - [Native Window Development](native-window-guidelines.md)
- [Using MindSpore Lite for Model Inference](native-window-guidelines.md)
# Using MindSpore Lite for Model Inference
## When to Use
MindSpore Lite is an AI engine that provides AI model inference for different hardware devices. It has been used in a wide range of fields, such as image classification, target recognition, facial recognition, and character recognition.
This document describes the general development process for MindSpore Lite model inference.
## Basic Concepts
Before getting started, you need to understand the following basic concepts:
**Tensor**: a special data structure that is similar to arrays and matrices. It is a basic data structure used in MindSpore Lite network operations.
**Float16 inference**: a mode in which Float16 is used for inference. Float16, also called half-precision, uses 16 bits to represent a number.
## Available APIs
APIs involved in MindSpore Lite model inference are categorized into context APIs, model APIs, and tensor APIs.
### Context APIs
| API | Description |
| ------------------ | ----------------- |
|OH_AI_ContextHandle OH_AI_ContextCreate()|Creates a context object.|
|void OH_AI_ContextSetThreadNum(OH_AI_ContextHandle context, int32_t thread_num)|Sets the number of runtime threads.|
| void OH_AI_ContextSetThreadAffinityMode(OH_AI_ContextHandle context, int mode)|Sets the affinity mode for binding runtime threads to CPU cores, which are categorized into little cores and big cores depending on the CPU frequency.|
|OH_AI_DeviceInfoHandle OH_AI_DeviceInfoCreate(OH_AI_DeviceType device_type)|Creates a runtime device information object.|
|void OH_AI_ContextDestroy(OH_AI_ContextHandle *context)|Destroys a context object.|
|void OH_AI_DeviceInfoSetEnableFP16(OH_AI_DeviceInfoHandle device_info, bool is_fp16)|Sets whether to enable float16 inference. This function is available only for CPU and GPU devices.|
|void OH_AI_ContextAddDeviceInfo(OH_AI_ContextHandle context, OH_AI_DeviceInfoHandle device_info)|Adds a runtime device information object.|
### Model APIs
| API | Description |
| ------------------ | ----------------- |
|OH_AI_ModelHandle OH_AI_ModelCreate()|Creates a model object.|
|OH_AI_Status OH_AI_ModelBuildFromFile(OH_AI_ModelHandle model, const char *model_path,OH_AI_ModelType odel_type, const OH_AI_ContextHandle model_context)|Loads and builds a MindSpore model from a model file.|
|void OH_AI_ModelDestroy(OH_AI_ModelHandle *model)|Destroys a model object.|
### Tensor APIs
| API | Description |
| ------------------ | ----------------- |
|OH_AI_TensorHandleArray OH_AI_ModelGetInputs(const OH_AI_ModelHandle model)|Obtains the input tensor array structure of a model.|
|int64_t OH_AI_TensorGetElementNum(const OH_AI_TensorHandle tensor)|Obtains the number of tensor elements.|
|const char *OH_AI_TensorGetName(const OH_AI_TensorHandle tensor)|Obtains the name of a tensor.|
|OH_AI_DataType OH_AI_TensorGetDataType(const OH_AI_TensorHandle tensor)|Obtains the tensor data type.|
|void *OH_AI_TensorGetMutableData(const OH_AI_TensorHandle tensor)|Obtains the pointer to variable tensor data.|
## How to Develop
The following figure shows the development process for MindSpore Lite model inference.
**Figure 1** Development process for MindSpore Lite model inference
![how-to-use-mindspore-lite](figures/01.png)
The development process consists of the following main steps:
1. Prepare the required model.
The required model can be downloaded directly or obtained using the model conversion tool.
- If the downloaded model is in the `.ms` format, you can use it directly for inference. The following uses the **mobilenetv2.ms** model as an example.
- If the downloaded model uses a third-party framework, such as TensorFlow, TensorFlow Lite, Caffe, or ONNX, you can use the [model conversion tool](https://www.mindspore.cn/lite/docs/en/r1.5/use/benchmark_tool.html) to convert it to the `.ms` format.
2. Create a context, and set parameters such as the number of runtime threads and device type.
```c
// Create a context, and set the number of runtime threads to 2 and the thread affinity mode to 1 (big cores first).
OH_AI_ContextHandle context = OH_AI_ContextCreate();
if (context == NULL) {
printf("OH_AI_ContextCreate failed.\n");
return OH_AI_STATUS_LITE_ERROR;
}
const int thread_num = 2;
OH_AI_ContextSetThreadNum(context, thread_num);
OH_AI_ContextSetThreadAffinityMode(context, 1);
// Set the device type to CPU, and disable Float16 inference.
OH_AI_DeviceInfoHandle cpu_device_info = OH_AI_DeviceInfoCreate(OH_AI_DEVICETYPE_CPU);
if (cpu_device_info == NULL) {
printf("OH_AI_DeviceInfoCreate failed.\n");
OH_AI_ContextDestroy(&context);
return OH_AI_STATUS_LITE_ERROR;
}
OH_AI_DeviceInfoSetEnableFP16(cpu_device_info, false);
OH_AI_ContextAddDeviceInfo(context, cpu_device_info);
```
3. Create, load, and build the model.
Call **OH_AI_ModelBuildFromFile** to load and build the model.
In this example, the **argv[1]** parameter passed to **OH_AI_ModelBuildFromFile** indicates the specified model file path.
```c
// Create a model.
OH_AI_ModelHandle model = OH_AI_ModelCreate();
if (model == NULL) {
printf("OH_AI_ModelCreate failed.\n");
OH_AI_ContextDestroy(&context);
return OH_AI_STATUS_LITE_ERROR;
}
// Load and build the model. The model type is OH_AI_ModelTypeMindIR.
int ret = OH_AI_ModelBuildFromFile(model, argv[1], OH_AI_ModelTypeMindIR, context);
if (ret != OH_AI_STATUS_SUCCESS) {
printf("OH_AI_ModelBuildFromFile failed, ret: %d.\n", ret);
OH_AI_ModelDestroy(&model);
return ret;
}
```
4. Input data.
Before executing model inference, you need to populate data to the input tensor. In this example, random data is used to populate the model.
```c
// Obtain the input tensor.
OH_AI_TensorHandleArray inputs = OH_AI_ModelGetInputs(model);
if (inputs.handle_list == NULL) {
printf("OH_AI_ModelGetInputs failed, ret: %d.\n", ret);
OH_AI_ModelDestroy(&model);
return ret;
}
// Use random data to populate the tensor.
ret = GenerateInputDataWithRandom(inputs);
if (ret != OH_AI_STATUS_SUCCESS) {
printf("GenerateInputDataWithRandom failed, ret: %d.\n", ret);
OH_AI_ModelDestroy(&model);
return ret;
}
```
5. Execute model inference.
Call **OH_AI_ModelPredict** to perform model inference.
```c
// Execute model inference.
OH_AI_TensorHandleArray outputs;
ret = OH_AI_ModelPredict(model, inputs, &outputs, NULL, NULL);
if (ret != OH_AI_STATUS_SUCCESS) {
printf("OH_AI_ModelPredict failed, ret: %d.\n", ret);
OH_AI_ModelDestroy(&model);
return ret;
}
```
6. Obtain the output.
After model inference is complete, you can obtain the inference result through the output tensor.
```c
// Obtain the output tensor and print the information.
for (size_t i = 0; i < outputs.handle_num; ++i) {
OH_AI_TensorHandle tensor = outputs.handle_list[i];
int64_t element_num = OH_AI_TensorGetElementNum(tensor);
printf("Tensor name: %s, tensor size is %zu ,elements num: %lld.\n", OH_AI_TensorGetName(tensor),
OH_AI_TensorGetDataSize(tensor), element_num);
const float *data = (const float *)OH_AI_TensorGetData(tensor);
printf("output data is:\n");
const int max_print_num = 50;
for (int j = 0; j < element_num && j <= max_print_num; ++j) {
printf("%f ", data[j]);
}
printf("\n");
}
```
7. Destroy the model.
If the MindSpore Lite inference framework is no longer needed, you need to destroy the created model.
```c
// Destroy the model.
OH_AI_ModelDestroy(&model);
```
## Verification
1. Compile **CMakeLists.txt**.
```cmake
cmake_minimum_required(VERSION 3.14)
project(Demo)
add_executable(demo main.c)
target_link_libraries(
demo
mindspore-lite.huawei
pthread
dl
)
```
- To use ohos-sdk for cross compilation, you need to set the native toolchain path for the CMake tool as follows: `-DCMAKE_TOOLCHAIN_FILE="/xxx/ohos-sdk/linux/native/build/cmake/ohos.toolchain.cmake"`.
- The toolchain builds a 64-bit application by default. To build a 32-bit application, add the following configuration: `-DOHOS_ARCH="armeabi-v7a"`.
2. Run the CMake tool.
- Use hdc_std to connect to the RK3568 development board and put **demo** and **mobilenetv2.ms** to the same directory on the board.
- Run the hdc_std shell command to access the development board, go to the directory where **demo** is located, and run the following command:
```shell
./demo mobilenetv2.ms
```
The inference is successful if the output is similar to the following:
```shell
# ./QuickStart ./mobilenetv2.ms
Tensor name: Softmax-65, tensor size is 4004 ,elements num: 1001.
output data is:
0.000018 0.000012 0.000026 0.000194 0.000156 0.001501 0.000240 0.000825 0.000016 0.000006 0.000007 0.000004 0.000004 0.000004 0.000015 0.000099 0.000011 0.000013 0.000005 0.000023 0.000004 0.000008 0.000003 0.000003 0.000008 0.000014 0.000012 0.000006 0.000019 0.000006 0.000018 0.000024 0.000010 0.000002 0.000028 0.000372 0.000010 0.000017 0.000008 0.000004 0.000007 0.000010 0.000007 0.000012 0.000005 0.000015 0.000007 0.000040 0.000004 0.000085 0.000023
```
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
Provides system event logging APIs for system HAP applications. Provides system event logging APIs for system HAP applications.
> **NOTE**<br> > **NOTE**
> - The initial APIs of this module are supported since API version 9. Newly added APIs will be marked with a superscript to indicate their earliest API version. > - The initial APIs of this module are supported since API version 9. Newly added APIs will be marked with a superscript to indicate their earliest API version.
> - The APIs of this module are system APIs. > - The APIs of this module are system APIs.
...@@ -19,7 +19,7 @@ Enumerates event types. ...@@ -19,7 +19,7 @@ Enumerates event types.
**System capability**: SystemCapability.HiviewDFX.HiSysEvent **System capability**: SystemCapability.HiviewDFX.HiSysEvent
| Name| Default Value| Description| | Name | Default Value | Description |
| -------- | -------- | -------- | | -------- | -------- | -------- |
| FAULT | 1 | Error event.| | FAULT | 1 | Error event.|
| STATISTIC | 2 | Statistic event.| | STATISTIC | 2 | Statistic event.|
...@@ -32,7 +32,7 @@ Defines a system event. ...@@ -32,7 +32,7 @@ Defines a system event.
**System capability**: SystemCapability.HiviewDFX.HiSysEvent **System capability**: SystemCapability.HiviewDFX.HiSysEvent
| Name| Type| Mandatory| Description| | Name| Type | Mandatory | Description |
| -------- | -------- | -------- | -------- | | -------- | -------- | -------- | -------- |
| domain | string | Yes| Event domain.| | domain | string | Yes| Event domain.|
| name | string | Yes| Event name.| | name | string | Yes| Event name.|
...@@ -50,7 +50,7 @@ Writes event information to the event file. This API uses an asynchronous callba ...@@ -50,7 +50,7 @@ Writes event information to the event file. This API uses an asynchronous callba
**Parameters** **Parameters**
| Name | Type | Mandatory| Description | | Name | Type | Mandatory | Description |
| --------- | ------------------------- | ---- | ------------------------------------------------------------ | | --------- | ------------------------- | ---- | ------------------------------------------------------------ |
| info | [SysEventInfo](#syseventinfo) | Yes| System event information.| | info | [SysEventInfo](#syseventinfo) | Yes| System event information.|
| callback | AsyncCallback&lt;void&gt; | Yes| Callback used to process the received return value.<br>- Value **0**: The event verification is successful, and the event will be written to the event file asynchronously. <br>- A value greater than **0**: Invalid parameters are present in the event, and the event will be written to the event file asynchronously after the invalid parameters are ignored.<br>- A value smaller than **0**: The event parameter verification fails, and the event will not be written to the event file.| | callback | AsyncCallback&lt;void&gt; | Yes| Callback used to process the received return value.<br>- Value **0**: The event verification is successful, and the event will be written to the event file asynchronously. <br>- A value greater than **0**: Invalid parameters are present in the event, and the event will be written to the event file asynchronously after the invalid parameters are ignored.<br>- A value smaller than **0**: The event parameter verification fails, and the event will not be written to the event file.|
...@@ -91,13 +91,13 @@ Writes event information to the event file. This API uses a promise to return th ...@@ -91,13 +91,13 @@ Writes event information to the event file. This API uses a promise to return th
**Parameters** **Parameters**
| Name | Type | Mandatory| Description| | Name | Type | Mandatory | Description|
| --------- | ----------------------- | ---- | --------------- | | --------- | ----------------------- | ---- | --------------- |
| info | [SysEventInfo](#syseventinfo) | Yes | System event information.| | info | [SysEventInfo](#syseventinfo) | Yes | System event information.|
**Return value** **Return value**
| Type | Description | | Type | Description |
| ------------------- | ------------------------------------------------------------ | | ------------------- | ------------------------------------------------------------ |
| Promise&lt;void&gt; | Promise used to return the result. Depending on whether event writing is successful, you can use the **then()** or **catch()** method to process the callback.| | Promise&lt;void&gt; | Promise used to return the result. Depending on whether event writing is successful, you can use the **then()** or **catch()** method to process the callback.|
...@@ -138,7 +138,7 @@ Enumerates matching rule types. ...@@ -138,7 +138,7 @@ Enumerates matching rule types.
**System capability**: SystemCapability.HiviewDFX.HiSysEvent **System capability**: SystemCapability.HiviewDFX.HiSysEvent
| Name| Default Value| Description| | Name | Default Value | Description |
| -------- | -------- | -------- | | -------- | -------- | -------- |
| WHOLE_WORD | 1 | Whole word matching.| | WHOLE_WORD | 1 | Whole word matching.|
| PREFIX | 2 | Prefix matching.| | PREFIX | 2 | Prefix matching.|
...@@ -150,7 +150,7 @@ Defines rules for event subscription. ...@@ -150,7 +150,7 @@ Defines rules for event subscription.
**System capability**: SystemCapability.HiviewDFX.HiSysEvent **System capability**: SystemCapability.HiviewDFX.HiSysEvent
| Name| Type| Mandatory| Description| | Name| Type | Mandatory | Description |
| -------- | -------- | -------- | -------- | | -------- | -------- | -------- | -------- |
| domain | string | Yes| Event domain.| | domain | string | Yes| Event domain.|
| name | string | Yes| Event name.| | name | string | Yes| Event name.|
...@@ -163,7 +163,7 @@ Defines a watcher for event subscription. ...@@ -163,7 +163,7 @@ Defines a watcher for event subscription.
**System capability**: SystemCapability.HiviewDFX.HiSysEvent **System capability**: SystemCapability.HiviewDFX.HiSysEvent
| Name| Type| Mandatory| Description| | Name| Type | Mandatory | Description |
| -------- | -------- | -------- | -------- | | -------- | -------- | -------- | -------- |
| rules | [WatchRule](#watchrule)[] | Yes| Array of matching rules for event subscription.| | rules | [WatchRule](#watchrule)[] | Yes| Array of matching rules for event subscription.|
| onEvent | function | Yes| Callback for event subscription: (info: [SysEventInfo](#syseventinfo)) => void| | onEvent | function | Yes| Callback for event subscription: (info: [SysEventInfo](#syseventinfo)) => void|
...@@ -181,7 +181,7 @@ Adds a watcher for event subscription. ...@@ -181,7 +181,7 @@ Adds a watcher for event subscription.
**Parameters** **Parameters**
| Name| Type| Mandatory| Description| | Name| Type | Mandatory | Description |
| ------ | ----------------------------- | ---- | ------------------------ | | ------ | ----------------------------- | ---- | ------------------------ |
| watcher | [Watcher](#watcher) | Yes| Watcher for event subscription.| | watcher | [Watcher](#watcher) | Yes| Watcher for event subscription.|
...@@ -223,7 +223,7 @@ Removes a watcher used for event subscription. ...@@ -223,7 +223,7 @@ Removes a watcher used for event subscription.
**Parameters** **Parameters**
| Name| Type | Mandatory| Description | | Name| Type | Mandatory | Description |
| ------ | ------------- | ---- | ------------------------ | | ------ | ------------- | ---- | ------------------------ |
| watcher | [Watcher](#watcher) | Yes| Watcher for event subscription.| | watcher | [Watcher](#watcher) | Yes| Watcher for event subscription.|
...@@ -260,7 +260,7 @@ Defines arguments for event query. ...@@ -260,7 +260,7 @@ Defines arguments for event query.
**System capability**: SystemCapability.HiviewDFX.HiSysEvent **System capability**: SystemCapability.HiviewDFX.HiSysEvent
| Name| Type| Mandatory| Description| | Name| Type | Mandatory | Description |
| -------- | -------- | -------- | -------- | | -------- | -------- | -------- | -------- |
| beginTime | number | Yes| Start time (13-digit timestamp) for event query.| | beginTime | number | Yes| Start time (13-digit timestamp) for event query.|
| endTime | number | Yes| End time (13-digit timestamp) for event query.| | endTime | number | Yes| End time (13-digit timestamp) for event query.|
...@@ -272,7 +272,7 @@ Defines rules for event query. ...@@ -272,7 +272,7 @@ Defines rules for event query.
**System capability**: SystemCapability.HiviewDFX.HiSysEvent **System capability**: SystemCapability.HiviewDFX.HiSysEvent
| Name| Type| Mandatory| Description| | Name| Type | Mandatory | Description |
| -------- | -------- | -------- | -------- | | -------- | -------- | -------- | -------- |
| domain | string | Yes| Event domain.| | domain | string | Yes| Event domain.|
| names | string[] | Yes| Array of event names.| | names | string[] | Yes| Array of event names.|
...@@ -283,7 +283,7 @@ Defines an event query instance. ...@@ -283,7 +283,7 @@ Defines an event query instance.
**System capability**: SystemCapability.HiviewDFX.HiSysEvent **System capability**: SystemCapability.HiviewDFX.HiSysEvent
| Name| Type| Mandatory| Description| | Name| Type | Mandatory | Description |
| -------- | -------- | -------- | -------- | | -------- | -------- | -------- | -------- |
| onQuery | function | Yes| Callback of queried events: (infos: [SysEventInfo](#syseventinfo)[]) => void| | onQuery | function | Yes| Callback of queried events: (infos: [SysEventInfo](#syseventinfo)[]) => void|
| onComplete | function | Yes| Callback of query result statistics: (reason: number, total: number) => void| | onComplete | function | Yes| Callback of query result statistics: (reason: number, total: number) => void|
...@@ -300,7 +300,7 @@ Queries system events. ...@@ -300,7 +300,7 @@ Queries system events.
**Parameters** **Parameters**
| Name| Type| Mandatory| Description| | Name| Type | Mandatory | Description |
| ------ | ----------------------------- | ---- | ------------------------ | | ------ | ----------------------------- | ---- | ------------------------ |
| queryArg | [QueryArg](#queryarg) | Yes | Arguments for event query.| | queryArg | [QueryArg](#queryarg) | Yes | Arguments for event query.|
| rules | [QueryRule](#queryrule)[] | Yes | Array of event query rules.| | rules | [QueryRule](#queryrule)[] | Yes | Array of event query rules.|
......
...@@ -64,7 +64,7 @@ Creates a Locale object. ...@@ -64,7 +64,7 @@ Creates a Locale object.
| Name | Type | Mandatory | Description | | Name | Type | Mandatory | Description |
| ------- | ------------- | ---- | ---------------------------- | | ------- | ------------- | ---- | ---------------------------- |
| locale | string | Yes | A string containing locale information, including the language, optional script, and region.| | locale | string | Yes | A string containing locale information, including the language, optional script, and region.|
| options | LocaleOptions | No | Options for creating the **Locale** object. | | options<sup>9+</sup> | [LocaleOptions](#localeoptions9) | No | Options for creating the **Locale** object. |
**Example** **Example**
``` ```
...@@ -181,7 +181,7 @@ Creates a **DateTimeOptions** object for the specified locale. ...@@ -181,7 +181,7 @@ Creates a **DateTimeOptions** object for the specified locale.
| Name | Type | Mandatory | Description | | Name | Type | Mandatory | Description |
| ------- | ----------------------------------- | ---- | ---------------------------- | | ------- | ----------------------------------- | ---- | ---------------------------- |
| locale | string \| Array&lt;string&gt; | Yes | A string containing locale information, including the language, optional script, and region.| | locale | string \| Array&lt;string&gt; | Yes | A string containing locale information, including the language, optional script, and region.|
| options | [DateTimeOptions](#datetimeoptions) | No | Options for creating a **DateTimeFormat** object. | | options<sup>9+</sup> | [DateTimeOptions](#datetimeoptions9) | No | Options for creating a **DateTimeFormat** object. |
**Example** **Example**
``` ```
...@@ -265,7 +265,7 @@ Obtains the formatting options for **DateTimeFormat** object. ...@@ -265,7 +265,7 @@ Obtains the formatting options for **DateTimeFormat** object.
| Type | Description | | Type | Description |
| ----------------------------------- | ----------------------------- | | ----------------------------------- | ----------------------------- |
| [DateTimeOptions](#datetimeoptions) | Formatting options for **DateTimeFormat** objects.| | [DateTimeOptions](#datetimeoptions9) | Formatting options for **DateTimeFormat** objects.|
**Example** **Example**
``` ```
...@@ -332,7 +332,7 @@ Parameters ...@@ -332,7 +332,7 @@ Parameters
| Name | Type | Mandatory | Description | | Name | Type | Mandatory | Description |
| ------- | ------------------------------- | ---- | ---------------------------- | | ------- | ------------------------------- | ---- | ---------------------------- |
| locale | string \| Array&lt;string&gt; | Yes | A string containing locale information, including the language, optional script, and region.| | locale | string \| Array&lt;string&gt; | Yes | A string containing locale information, including the language, optional script, and region.|
| options | [NumberOptions](#numberoptions) | No | Options for creating a **NumberFormat** object. | | options<sup>9+</sup> | [NumberOptions](#numberoptions9) | No | Options for creating a **NumberFormat** object. |
**Example** **Example**
``` ```
...@@ -380,7 +380,7 @@ Obtains the options of the **NumberFormat** object. ...@@ -380,7 +380,7 @@ Obtains the options of the **NumberFormat** object.
| Type | Description | | Type | Description |
| ------------------------------- | --------------------------- | | ------------------------------- | --------------------------- |
| [NumberOptions](#numberoptions) | Formatting options for **NumberFormat** objects.| | [NumberOptions](#numberoptions9) | Formatting options for **NumberFormat** objects.|
**Example** **Example**
...@@ -449,7 +449,7 @@ Creates a Collator object. ...@@ -449,7 +449,7 @@ Creates a Collator object.
| Name | Type | Mandatory | Description | | Name | Type | Mandatory | Description |
| ------- | ----------------------------------- | ---- | ---------------------------- | | ------- | ----------------------------------- | ---- | ---------------------------- |
| locale | string \| Array&lt;string&gt; | Yes | A string containing locale information, including the language, optional script, and region.| | locale | string \| Array&lt;string&gt; | Yes | A string containing locale information, including the language, optional script, and region.|
| options | [CollatorOptions](#collatoroptions) | No | Options for creating a **Collator** object. | | options<sup>9+</sup> | [CollatorOptions](#collatoroptions9) | No | Options for creating a **Collator** object. |
**Example** **Example**
``` ```
...@@ -497,7 +497,7 @@ Returns properties reflecting the locale and collation options of a **Collator** ...@@ -497,7 +497,7 @@ Returns properties reflecting the locale and collation options of a **Collator**
| Type | Description | | Type | Description |
| ----------------------------------- | ----------------- | | ----------------------------------- | ----------------- |
| [CollatorOptions](#collatoroptions) | Properties of the **Collator** object.| | [CollatorOptions](#collatoroptions9) | Properties of the **Collator** object.|
**Example** **Example**
...@@ -553,7 +553,7 @@ Parameters ...@@ -553,7 +553,7 @@ Parameters
| Name | Type | Mandatory | Description | | Name | Type | Mandatory | Description |
| ------- | ---------------------------------------- | ---- | ---------------------------- | | ------- | ---------------------------------------- | ---- | ---------------------------- |
| locale | string \| Array&lt;string&gt; | Yes | A string containing locale information, including the language, optional script, and region.| | locale | string \| Array&lt;string&gt; | Yes | A string containing locale information, including the language, optional script, and region.|
| options | [PluralRulesOptions](#pluralrulesoptions) | No | Options for creating a **PluralRules** object. | | options<sup>9+</sup> | [PluralRulesOptions](#pluralrulesoptions9) | No | Options for creating a **PluralRules** object. |
**Example** **Example**
``` ```
...@@ -635,7 +635,7 @@ Creates a **RelativeTimeFormat** object. ...@@ -635,7 +635,7 @@ Creates a **RelativeTimeFormat** object.
| Name | Type | Mandatory | Description | | Name | Type | Mandatory | Description |
| ------- | ---------------------------------------- | ---- | ---------------------------- | | ------- | ---------------------------------------- | ---- | ---------------------------- |
| locale | string \| Array&lt;string&gt; | Yes | A string containing locale information, including the language, optional script, and region.| | locale | string \| Array&lt;string&gt; | Yes | A string containing locale information, including the language, optional script, and region.|
| options | [RelativeTimeFormatInputOptions](#relativetimeformatinputoptions) | No | Options for creating a **RelativeTimeFormat** object. | | options<sup>9+</sup> | [RelativeTimeFormatInputOptions](#relativetimeformatinputoptions9) | No | Options for creating a **RelativeTimeFormat** object. |
**Example** **Example**
``` ```
...@@ -711,7 +711,7 @@ Obtains the formatting options for **RelativeTimeFormat** objects. ...@@ -711,7 +711,7 @@ Obtains the formatting options for **RelativeTimeFormat** objects.
| Type | Description | | Type | Description |
| ---------------------------------------- | --------------------------------- | | ---------------------------------------- | --------------------------------- |
| [RelativeTimeFormatResolvedOptions](#relativetimeformatresolvedoptions) | Formatting options for **RelativeTimeFormat** objects.| | [RelativeTimeFormatResolvedOptions](#relativetimeformatresolvedoptions8) | Formatting options for **RelativeTimeFormat** objects.|
**Example** **Example**
``` ```
......
...@@ -110,7 +110,7 @@ connection.hasDefaultNet().then(function (has) { ...@@ -110,7 +110,7 @@ connection.hasDefaultNet().then(function (has) {
getAllNets(callback: AsyncCallback&lt;Array&lt;NetHandle&gt;&gt;): void getAllNets(callback: AsyncCallback&lt;Array&lt;NetHandle&gt;&gt;): void
Obtains the list of all active data networks. This API uses an asynchronous callback to return the result. Obtains the list of all connected networks. This API uses an asynchronous callback to return the result.
**Required permission**: ohos.permission.GET_NETWORK_INFO **Required permission**: ohos.permission.GET_NETWORK_INFO
...@@ -136,7 +136,7 @@ connection.getAllNets(function (error, nets) { ...@@ -136,7 +136,7 @@ connection.getAllNets(function (error, nets) {
getAllNets(): Promise&lt;Array&lt;NetHandle&gt;&gt; getAllNets(): Promise&lt;Array&lt;NetHandle&gt;&gt;
Obtains the list of all active data networks. This API uses a promise to return the result. Obtains the list of all connected networks. This API uses a promise to return the result.
**Required permission**: ohos.permission.GET_NETWORK_INFO **Required permission**: ohos.permission.GET_NETWORK_INFO
...@@ -280,7 +280,7 @@ connection.getDefaultNet().then(function (netHandle) { ...@@ -280,7 +280,7 @@ connection.getDefaultNet().then(function (netHandle) {
reportNetConnected(netHandle: NetHandle, callback: AsyncCallback&lt;void&gt;): void reportNetConnected(netHandle: NetHandle, callback: AsyncCallback&lt;void&gt;): void
Reports connection of the data network. This API uses an asynchronous callback to return the result. Reports connection of the data network to the network management module. This API uses an asynchronous callback to return the result. If this API is called, the application considers that the network connection state (**ohos.net.connection.NetCap.NET_CAPABILITY_VAILDATED**) is inconsistent with that in the network management module.
**Permission required**: ohos.permission.GET_NETWORK_INFO and ohos.permission.INTERNET **Permission required**: ohos.permission.GET_NETWORK_INFO and ohos.permission.INTERNET
...@@ -308,7 +308,7 @@ connection.getDefaultNet().then(function (netHandle) { ...@@ -308,7 +308,7 @@ connection.getDefaultNet().then(function (netHandle) {
reportNetConnected(netHandle: NetHandle): Promise&lt;void&gt; reportNetConnected(netHandle: NetHandle): Promise&lt;void&gt;
Reports connection of the data network. This API uses a promise to return the result. Reports connection of the data network to the network management module. This API uses a promise to return the result. If this API is called, the application considers that the network connection state (**ohos.net.connection.NetCap.NET_CAPABILITY_VAILDATED**) is inconsistent with that in the network management module.
**Permission required**: ohos.permission.GET_NETWORK_INFO and ohos.permission.INTERNET **Permission required**: ohos.permission.GET_NETWORK_INFO and ohos.permission.INTERNET
...@@ -341,7 +341,7 @@ connection.getDefaultNet().then(function (netHandle) { ...@@ -341,7 +341,7 @@ connection.getDefaultNet().then(function (netHandle) {
reportNetDisconnected(netHandle: NetHandle, callback: AsyncCallback&lt;void&gt;): void reportNetDisconnected(netHandle: NetHandle, callback: AsyncCallback&lt;void&gt;): void
Reports disconnection of the data network. This API uses an asynchronous callback to return the result. Reports disconnection of the data network to the network management module. This API uses an asynchronous callback to return the result. If this API is called, the application considers that the network connection state (**ohos.net.connection.NetCap.NET_CAPABILITY_VAILDATED**) is inconsistent with that in the network management module.
**Permission required**: ohos.permission.GET_NETWORK_INFO and ohos.permission.INTERNET **Permission required**: ohos.permission.GET_NETWORK_INFO and ohos.permission.INTERNET
...@@ -369,7 +369,8 @@ connection.getDefaultNet().then(function (netHandle) { ...@@ -369,7 +369,8 @@ connection.getDefaultNet().then(function (netHandle) {
reportNetDisconnected(netHandle: NetHandle): Promise&lt;void&gt; reportNetDisconnected(netHandle: NetHandle): Promise&lt;void&gt;
Reports disconnection of the data network. This API uses a promise to return the result. Reports disconnection of the data network to the network management module. This API uses a promise to return the result. If this API is called, the application considers that the network connection state (**ohos.net.connection.NetCap.NET_CAPABILITY_VAILDATED**) is inconsistent with that in the network management module.
**Permission required**: ohos.permission.GET_NETWORK_INFO and ohos.permission.INTERNET **Permission required**: ohos.permission.GET_NETWORK_INFO and ohos.permission.INTERNET
...@@ -558,7 +559,7 @@ connection.disableAirplaneMode().then(function (error) { ...@@ -558,7 +559,7 @@ connection.disableAirplaneMode().then(function (error) {
createNetConnection(netSpecifier?: NetSpecifier, timeout?: number): NetConnection createNetConnection(netSpecifier?: NetSpecifier, timeout?: number): NetConnection
Obtains the handle of the network specified by **netSpecifier**. Creates a **NetConnection** object. **netSpecifier** specifies the network, and **timeout** specifies the timeout interval in ms. **timeout** is configurable only when **netSpecifier** is specified. If neither of them is present, the default network is used.
**System capability**: SystemCapability.Communication.NetManager.Core **System capability**: SystemCapability.Communication.NetManager.Core
...@@ -950,9 +951,9 @@ Defines the network capability. ...@@ -950,9 +951,9 @@ Defines the network capability.
| ------------------------ | ---- | ---------------------- | | ------------------------ | ---- | ---------------------- |
| NET_CAPABILITY_MMS | 0 | The network can connect to the carrier's Multimedia Messaging Service Center (MMSC) to send and receive multimedia messages.| | NET_CAPABILITY_MMS | 0 | The network can connect to the carrier's Multimedia Messaging Service Center (MMSC) to send and receive multimedia messages.|
| NET_CAPABILITY_NOT_METERED | 11 | The network traffic is not metered.| | NET_CAPABILITY_NOT_METERED | 11 | The network traffic is not metered.|
| NET_CAPABILITY_INTERNET | 12 | The network can connect to the Internet.| | NET_CAPABILITY_INTERNET | 12 | The network has the Internet access capability, which is set by the network provider.|
| NET_CAPABILITY_NOT_VPN | 15 | The network does not use a Virtual Private Network (VPN).| | NET_CAPABILITY_NOT_VPN | 15 | The network does not use a Virtual Private Network (VPN).|
| NET_CAPABILITY_VALIDATED | 16 | The network is available. | | NET_CAPABILITY_VALIDATED | 16 | The Internet access capability of the network is successfully verified by the network management module. |
## NetBearType ## NetBearType
......
...@@ -433,7 +433,7 @@ ws.off('open', callback1); ...@@ -433,7 +433,7 @@ ws.off('open', callback1);
on\(type: 'message', callback: AsyncCallback<string | ArrayBuffer\>\): void on\(type: 'message', callback: AsyncCallback<string | ArrayBuffer\>\): void
Enables listening for the **message** events of a WebSocket connection. This API uses an asynchronous callback to return the result. Enables listening for the **message** events of a WebSocket connection. This API uses an asynchronous callback to return the result. The maximum length of each message is 4 KB. If the length exceeds 4 KB, the message is automatically fragmented.
>![](public_sys-resources/icon-note.gif) **NOTE:** >![](public_sys-resources/icon-note.gif) **NOTE:**
>The data in **AsyncCallback** can be in the format of string\(API 6\) or ArrayBuffer\(API 8\). >The data in **AsyncCallback** can be in the format of string\(API 6\) or ArrayBuffer\(API 8\).
...@@ -462,7 +462,7 @@ ws.on('message', (err, value) => { ...@@ -462,7 +462,7 @@ ws.on('message', (err, value) => {
off\(type: 'message', callback?: AsyncCallback<string | ArrayBuffer\>\): void off\(type: 'message', callback?: AsyncCallback<string | ArrayBuffer\>\): void
Disables listening for the **message** events of a WebSocket connection. This API uses an asynchronous callback to return the result. Disables listening for the **message** events of a WebSocket connection. This API uses an asynchronous callback to return the result. The maximum length of each message is 4 KB. If the length exceeds 4 KB, the message is automatically fragmented.
>![](public_sys-resources/icon-note.gif) **NOTE:** >![](public_sys-resources/icon-note.gif) **NOTE:**
>The data in **AsyncCallback** can be in the format of string\(API 6\) or ArrayBuffer\(API 8\). >The data in **AsyncCallback** can be in the format of string\(API 6\) or ArrayBuffer\(API 8\).
......
...@@ -63,7 +63,7 @@ The appspawn module is used only for the standard system. ...@@ -63,7 +63,7 @@ The appspawn module is used only for the standard system.
- Support for cold start of applications by using the aa command - Support for cold start of applications by using the aa command
``` ```
param set appspawn.cold.boot true // Enable cold start. param set startup.appspawn.cold.boot 1 // Enable cold start.
aa start -d 12345 -a $name -b $package -C aa start -d 12345 -a $name -b $package -C
Reference command: Reference command:
aa start -d 12345 -a ohos.acts.startup.sysparam.function.MainAbility -b ohos.acts.startup.sysparam.function -C aa start -d 12345 -a ohos.acts.startup.sysparam.function.MainAbility -b ohos.acts.startup.sysparam.function -C
...@@ -166,5 +166,5 @@ The following is the sample code for adding product-specific configuration for t ...@@ -166,5 +166,5 @@ The following is the sample code for adding product-specific configuration for t
<br>Applications fail to be started by running the cold start command. <br>Applications fail to be started by running the cold start command.
**Solution** **Solution**
<br>1. Enable cold start by setting **param set appspawn.cold.boot true**. <br>1. Enable cold start by setting **param set startup.appspawn.cold.boot 1**.
<br>2. Make sure that the cold start command is correct. <br>2. Make sure that the cold start command is correct.
...@@ -163,6 +163,22 @@ By parsing the <strong>*.cfg</strong> file, you can obtain **service** fields, a ...@@ -163,6 +163,22 @@ By parsing the <strong>*.cfg</strong> file, you can obtain **service** fields, a
| int StartServiceByTimer(const char *serviceName, uint64_t timeout) | Starts a service by timer.| Return value: Returns **0** if the operation is successful; returns **-1** otherwise.<br> Arguments:<br> **serviceName**: service name.<br> timeout: timeout interval.| | int StartServiceByTimer(const char *serviceName, uint64_t timeout) | Starts a service by timer.| Return value: Returns **0** if the operation is successful; returns **-1** otherwise.<br> Arguments:<br> **serviceName**: service name.<br> timeout: timeout interval.|
| int StopServiceTimer(const char *serviceName) | Stops a service timer.| Return value: Returns **0** if the operation is successful; returns **-1** otherwise.<br> Arguments:<br> **serviceName**: service name.| | int StopServiceTimer(const char *serviceName) | Stops a service timer.| Return value: Returns **0** if the operation is successful; returns **-1** otherwise.<br> Arguments:<br> **serviceName**: service name.|
- DAC configuration for service control APIs
Go to **/base/startup/init/services/etc/group** and add the correct user ID to **servicectrl**. For example:
```java
servicectrl:x:1050:root,shell,system,samgr,hdf_devmgr
```
- SELinux configuration for service control APIs
Add the required SELinux permissions to the **init.te** file. For example, grant the system parameter write permission for services such as **init**, **samgr**, and **hdf_devmgr**.
```java
allow { init samgr hdf_devmgr } servicectrl_param:parameter_service { set };
```
### How to Develop ### How to Develop
The following describes how to add a system service named **MySystemApp**: The following describes how to add a system service named **MySystemApp**:
......
...@@ -98,6 +98,55 @@ Each subsystem defines the system parameters of its own modules, including the s ...@@ -98,6 +98,55 @@ Each subsystem defines the system parameters of its own modules, including the s
![UGO rule](figure/dac-definition.png) ![UGO rule](figure/dac-definition.png)
- SELinux policy for system parameter configuration
- Add SELinux tags.
To add a SELinux tag to system parameters, you first need to define the tag in the **/base/security/selinux/sepolicy/base/public/parameter.te** file. For example:
```java
type servicectrl_param, parameter_attr
```
After the tag is defined, add the system parameter prefix associated with the tag to **/base/security/selinux/sepolicy/base/public/parameter_contexts**. The following uses the prefix **ohos.servicectrl** as an example:
```java
ohos.servicectrl. u:object_r:servicectrl_param:s0
```
- Grant operation permissions. For example, to grant operation permissions such as map for the init process, add the following content to the **/base/security/selinux/sepolicy/ohos_policy/startup/init/public/init.te** file:
```java
allow servicectrl_param tmpfs:filesystem associate;
allow init servicectrl_param:file { map open read relabelto relabelfrom };
```
- Set the write permission. For example, grant the system parameter write permission for services such as **init**, **samgr**, and **hdf_devmgr**.
```java
allow { init samgr hdf_devmgr } servicectrl_param:parameter_service { set };
```
- Set the read permission. If you want to grant the permission only for certain services, replace **xxx** with the services in the following code:
```java
allow { xxx } servicectrl_param:file { map open read };
```
- If you want to grant the permission for all services, use the following code:
```java
allow { domain -limit_domain } servicectrl_param:file { map open read };
```
- Suggestions
Keep only two system parameter tags for each subsystem:
- A private tag to control system parameter settings.
- A public tag to grant access from all services.
- Loading sequence - Loading sequence
The following table provides the sequence of loading system parameters. The following table provides the sequence of loading system parameters.
...@@ -111,6 +160,22 @@ Each subsystem defines the system parameters of its own modules, including the s ...@@ -111,6 +160,22 @@ Each subsystem defines the system parameters of its own modules, including the s
| System parameters| /system/etc/param/*.para | Load the parameters defined by each subsystem. If a system parameter already exists, ignore it.| | System parameters| /system/etc/param/*.para | Load the parameters defined by each subsystem. If a system parameter already exists, ignore it.|
| Persistent parameters| /data/parameters/ | If persistent parameters exist, load them at last. Persistent parameters will overwrite the default system parameters that have been loaded.| | Persistent parameters| /data/parameters/ | If persistent parameters exist, load them at last. Persistent parameters will overwrite the default system parameters that have been loaded.|
#### System Parameter Tag File Size
If one tag corresponds to more than five system parameters, you need to set the size of the system parameter tag file in **/base/startup/init/services/etc/param/ohos.para.size**. The size value is **512** by default.
Configuring rule:
System parameter tag = Size
Example:
```java
startup_init_param=40960
```
### Constraints ### Constraints
The service management module is available only for the mini system and standard system. The service management module is available only for the mini system and standard system.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册