From 0544ebc50db8095dfd5445def59f10e9d6008618 Mon Sep 17 00:00:00 2001 From: shawn_he Date: Tue, 11 Apr 2023 10:28:31 +0800 Subject: [PATCH] update doc Signed-off-by: shawn_he --- .../connectivity/http-request.md | 79 ++- en/application-dev/faqs/Readme-EN.md | 1 - en/application-dev/faqs/faqs-hdc-std.md | 87 --- .../reference/apis/Readme-EN.md | 1 + .../reference/apis/js-apis-contact.md | 93 ++- .../reference/apis/js-apis-http.md | 22 +- .../reference/apis/js-apis-i18n.md | 69 +++ .../reference/apis/js-apis-net-mdns.md | 551 ++++++++++++++++++ .../reference/apis/js-apis-power.md | 32 +- .../apis/js-apis-system-brightness.md | 3 +- .../reference/apis/js-apis-telephony-data.md | 44 +- .../reference/errorcodes/Readme-EN.md | 1 + .../errorcodes/errorcode-net-mdns.md | 117 ++++ en/device-dev/subsystems/Readme-EN.md | 4 +- .../subsystems/figures/nnrt_arch_diagram.png | Bin 0 -> 46388 bytes .../subsystems/figures/nnrt_dev_flow.png | Bin 0 -> 36978 bytes .../subsystems/subsys-ai-nnrt-guide.md | 404 +++++++++++++ .../subsystems/subsys-dfx-hicollie.md | 276 +++------ .../subsystems/subsys-dfx-hidumper.md | 29 +- .../subsystems/subsys-dfx-hitracechain.md | 2 - .../subsystems/subsys-dfx-hitracemeter.md | 2 +- 21 files changed, 1425 insertions(+), 392 deletions(-) delete mode 100644 en/application-dev/faqs/faqs-hdc-std.md create mode 100644 en/application-dev/reference/apis/js-apis-net-mdns.md create mode 100644 en/application-dev/reference/errorcodes/errorcode-net-mdns.md create mode 100644 en/device-dev/subsystems/figures/nnrt_arch_diagram.png create mode 100644 en/device-dev/subsystems/figures/nnrt_dev_flow.png create mode 100644 en/device-dev/subsystems/subsys-ai-nnrt-guide.md diff --git a/en/application-dev/connectivity/http-request.md b/en/application-dev/connectivity/http-request.md index 6204682cde..39ada2bc9b 100644 --- a/en/application-dev/connectivity/http-request.md +++ b/en/application-dev/connectivity/http-request.md @@ -30,7 +30,7 @@ The following table provides only a simple description of the related APIs. For | on\('dataProgress'\)10+ | Registers an observer for events indicating progress of receiving HTTP streaming responses. | | off\('dataProgress'\)10+ | Unregisters the observer for events indicating progress of receiving HTTP streaming responses.| -## How to Develop +## How to Develop request APIs 1. Import the **http** namespace from **@ohos.net.http.d.ts**. 2. Call **createHttp()** to create an **HttpRequest** object. @@ -89,3 +89,80 @@ httpRequest.request( } ); ``` + +## How to Develop request2 APIs + +1. Import the **http** namespace from **@ohos.net.http.d.ts**. +2. Call **createHttp()** to create an **HttpRequest** object. +3. Depending on your need, call **on()** of the **HttpRequest** object to subscribe to HTTP response header events as well as events indicating receiving of HTTP streaming responses, progress of receiving HTTP streaming responses, and completion of receiving HTTP streaming responses. +4. Call **request2()** to initiate a network request. You need to pass in the URL and optional parameters of the HTTP request. +5. Parse the returned response code as needed. +6. Call **off()** of the **HttpRequest** object to unsubscribe from the related events. +7. Call **httpRequest.destroy()** to release resources after the request is processed. + +```js +// Import the http namespace. +import http from '@ohos.net.http' + +// Each httpRequest corresponds to an HTTP request task and cannot be reused. +let httpRequest = http.createHttp(); +// Subscribe to HTTP response header events. +httpRequest.on('headersReceive', (header) => { + console.info('header: ' + JSON.stringify(header)); +}); +// Subscribe to events indicating receiving of HTTP streaming responses. +let res = ''; +httpRequest.on('dataReceive', (data) => { + res += data; + console.info('res: ' + res); +}); +// Subscribe to events indicating completion of receiving HTTP streaming responses. +httpRequest.on('dataEnd', () => { + console.info('No more data in response, data receive end'); +}); +// Subscribe to events indicating progress of receiving HTTP streaming responses. +httpRequest.on('dataProgress', (data) => { + console.log("dataProgress receiveSize:" + data.receiveSize+ ", totalSize:" + data.totalSize); +}); + +httpRequest.request2( + // Customize EXAMPLE_URL in extraData on your own. It is up to you whether to add parameters to the URL. + "EXAMPLE_URL", + { + method: http.RequestMethod.POST, // Optional. The default value is http.RequestMethod.GET. + // You can add header fields based on service requirements. + header: { + 'Content-Type': 'application/json' + }, + // This field is used to transfer data when the POST request is used. + extraData: { + "data": "data to send", + }, + expectDataType: http.HttpDataType.STRING, // Optional. This field specifies the type of the return data. + usingCache: true, // Optional. The default value is true. + priority: 1, // Optional. The default value is 1. + connectTimeout: 60000 // Optional. The default value is 60000, in ms. + readTimeout: 60000, // Optional. The default value is 60000, in ms. If a large amount of data needs to be transmitted, you are advised to set this parameter to a larger value to ensure normal data transmission. + usingProtocol: http.HttpProtocol.HTTP1_1, // Optional. The default protocol type is automatically specified by the system. + }, (err, data) => { + console.info('error:' + JSON.stringify(err)); + console.info('ResponseCode :' + JSON.stringify(data)); + // Unsubscribe from HTTP Response Header events. + httpRequest.off('headersReceive'); + // Unregister the observer for events indicating receiving of HTTP streaming responses. + httpRequest.off('dataReceive'); + // Unregister the observer for events indicating progress of receiving HTTP streaming responses. + httpRequest.off('dataProgress'); + // Unregister the observer for events indicating completion of receiving HTTP streaming responses. + httpRequest.off('dataEnd'); + // Call the destroy() method to release resources after HttpRequest is complete. + httpRequest.destroy(); + } +); + +``` + +## Samples +The following sample is provided to help you better understand how to develop the HTTP data request feature: +- [HTTP Data Request (ArkTS) (API9)](https://gitee.com/openharmony/applications_app_samples/tree/master/code/BasicFeature/Connectivity/Http) +- [HTTP Communication (ArkTS) (API9)](https://gitee.com/openharmony/codelabs/tree/master/NetworkManagement/SmartChatEtsOH) diff --git a/en/application-dev/faqs/Readme-EN.md b/en/application-dev/faqs/Readme-EN.md index 7eb9cad6b5..63535a32ae 100644 --- a/en/application-dev/faqs/Readme-EN.md +++ b/en/application-dev/faqs/Readme-EN.md @@ -18,5 +18,4 @@ - [Native API Usage](faqs-native.md) - [Usage of Third- and Fourth-Party Libraries](faqs-third-party-library.md) - [IDE Usage](faqs-ide.md) -- [hdc_std Command Usage](faqs-hdc-std.md) - [Development Board](faqs-development-board.md) \ No newline at end of file diff --git a/en/application-dev/faqs/faqs-hdc-std.md b/en/application-dev/faqs/faqs-hdc-std.md deleted file mode 100644 index 60f93da61d..0000000000 --- a/en/application-dev/faqs/faqs-hdc-std.md +++ /dev/null @@ -1,87 +0,0 @@ -# hdc_std Command Usage - -## Common Log Commands - -Applicable to: OpenHarmony SDK 3.2.2.5 - -Clearing logs: hdc_std shell hilog -r - -Increasing the buffer size to 20 MB: hdc_std shell hilog -G 20M - -Capturing logs: hdc_std shell hilog > log.txt - -## What should I do to avoid log flow control? - -Applicable to: OpenHarmony SDK 3.2.5.3, stage model of API version 9 - -- Disabling log flow control: hdc_std shell hilog -Q pidoff - -- Disabling the privacy flag: hdc_std shell hilog -p off - -- Increasing the log buffer to 200 MB: hdc_std shell hilog -G 200M - -- Enabling the log function of the specific domain (that is, disabling the global log function): hdc_std shell hilog –b D –D 0xd0xxxxx - -After performing the preceding operations, restart the DevEco Studio. - -## What should I do if the HAP installed on the development board through the IDE cannot be opened? - -Applicable to: OpenHarmony SDK 3.2.5.3, stage model of API version 9 - -Check whether the SDK version is consistent with the system version on the development board. You are advised to use the SDK version and system version that are released on the same day. - -## How do I upload files using the hdc command? - -Applicable to: OpenHarmony SDK 3.2.2.5 - -Run the **hdc_std file send** command. - -## How do I prevent the screen of the RK3568 development board from turning off? - -Applicable to: OpenHarmony SDK 3.2.5.3, stage model of API version 9 - -Run the **hdc_std shell "power-shell setmode 602"** command. - -## How do I start an ability using the hdc command? - -Applicable to: OpenHarmony SDK 3.2.5.3, stage model of API version 9 - -Run the **hdc\_std shell aa start -a AbilityName -b bundleName -m moduleName** command. - -## How do I change the read and write permissions on a file directory on the development board? - -Applicable to: OpenHarmony SDK 3.2.5.6, stage model of API version 9 - -Run the **hdc\_std shell mount -o remount,rw /** command. - -## What should I do if the error message "Unknown file option -r" is displayed when hdc_std file recv is run? - -Applicable to: OpenHarmony SDK 3.2.5.6, stage model of API version 9 - -1. Use the the hdc tool in the device image or SDK of the same version. - -2. Remove any Chinese characters or spaces from the directory specified for the hdc tool. - -## How do I uninstall an application using the hdc command? - -Applicable to: OpenHarmony SDK 3.2.2.5 - -Run the **hdc\_std uninstall [-k] [package_name]** command. - -## How do I check whether the system is 32-bit or 64-bit? - -Applicable to: OpenHarmony SDK 3.2.5.5 - -Run the **hdc\_std shell getconf LONG_BIT** command. - -If **64** is returned, the system is a 64-bit one. Otherwise, the system is a 32-bit one. - -## How do I view the component tree structure? - -Applicable to: OpenHarmony SDK 3.2.5.5 - -1. Run the **hdc\_std shell** command to launch the CLI. - -2. Run the **aa dump -a** command to find **abilityID**. - -3. Run the **aa dump -i [abilityID] -c -render** command to view the component tree. diff --git a/en/application-dev/reference/apis/Readme-EN.md b/en/application-dev/reference/apis/Readme-EN.md index 1e54b48558..c42f178f43 100644 --- a/en/application-dev/reference/apis/Readme-EN.md +++ b/en/application-dev/reference/apis/Readme-EN.md @@ -264,6 +264,7 @@ - [@ohos.net.socket (Socket Connection)](js-apis-socket.md) - [@ohos.net.webSocket (WebSocket Connection)](js-apis-webSocket.md) - [@ohos.request (Upload and Download)](js-apis-request.md) + - [@ohos.net.mdns (mDNS Management)](js-apis-net-mdns) - Connectivity - [@ohos.bluetoothManager (Bluetooth)(js-apis-bluetoothManager.md) diff --git a/en/application-dev/reference/apis/js-apis-contact.md b/en/application-dev/reference/apis/js-apis-contact.md index bcc8b36fc9..358d4e9538 100644 --- a/en/application-dev/reference/apis/js-apis-contact.md +++ b/en/application-dev/reference/apis/js-apis-contact.md @@ -1,5 +1,7 @@ # @ohos.contact (Contacts) +The **contact** module provides contact management functions, such as adding, deleting, and updating contacts. + >**NOTE** > >The initial APIs of this module are supported since API version 7. Newly added APIs will be marked with a superscript to indicate their earliest API version. @@ -7,7 +9,7 @@ ## Modules to Import -```js +``` import contact from '@ohos.contact'; ``` @@ -183,7 +185,7 @@ Updates a contact based on the specified contact information. This API uses an a updateContact(contact: Contact, attrs: ContactAttributes, callback: AsyncCallback<void>): void -Updates a contact based on the specified contact information and attributes. This API uses an asynchronous callback to return the result. +Updates a contact based on the specified contact information. This API uses an asynchronous callback to return the result. **Permission required**: ohos.permission.WRITE_CONTACTS @@ -234,7 +236,6 @@ Updates a contact based on the specified contact information and attributes. Thi | attrs | [ContactAttributes](#contactattributes) | No | List of contact attributes.| **Return Value** - | Type | Description | | ------------------- | ------------------------------------------------- | | Promise<void> | Promise used to return the result.| @@ -418,7 +419,7 @@ Queries my card. This API uses an asynchronous callback to return the result. queryMyCard(attrs: ContactAttributes, callback: AsyncCallback<Contact>): void -Queries my card based on the specified contact attributes. This API uses an asynchronous callback to return the result. +Queries my card. This API uses an asynchronous callback to return the result. **Permission required**: ohos.permission.READ_CONTACTS @@ -463,7 +464,6 @@ Queries my card based on the specified contact attributes. This API uses a promi | attrs | [ContactAttributes](#contactattributes) | No | List of contact attributes.| **Return Value** - | Type | Description | | ---------------------------------- | ------------------------------------------- | | Promise<[Contact](#contact)> | Promise used to return the result.| @@ -488,8 +488,6 @@ selectContact(callback: AsyncCallback<Array<Contact>>): void Selects a contact. This API uses an asynchronous callback to return the result. -**Permission required**: ohos.permission.READ_CONTACTS - **System capability**: SystemCapability.Applications.Contacts **Parameters** @@ -517,8 +515,6 @@ selectContact(): Promise<Array<Contact>> Selects a contact. This API uses a promise to return the result. -**Permission required**: ohos.permission.READ_CONTACTS - **System capability**: SystemCapability.Applications.Contacts **Return Value** @@ -573,7 +569,7 @@ Queries a contact based on the specified key. This API uses an asynchronous call queryContact(key: string, holder: Holder, callback: AsyncCallback<Contact>): void -Queries contacts based on the specified key and application. This API uses an asynchronous callback to return the result. +Queries a contact based on the specified key. This API uses an asynchronous callback to return the result. **Permission required**: ohos.permission.READ_CONTACTS @@ -608,7 +604,7 @@ Queries contacts based on the specified key and application. This API uses an as queryContact(key: string, attrs: ContactAttributes, callback: AsyncCallback<Contact>): void -Queries contacts based on the specified key and attributes. This API uses an asynchronous callback to return the result. +Queries a contact based on the specified key. This API uses an asynchronous callback to return the result. **Permission required**: ohos.permission.READ_CONTACTS @@ -641,7 +637,7 @@ Queries contacts based on the specified key and attributes. This API uses an asy queryContact(key: string, holder: Holder, attrs: ContactAttributes, callback: AsyncCallback<Contact>): void -Queries contacts based on the specified key, application, and attributes. This API uses an asynchronous callback to return the result. +Queries a contact based on the specified key. This API uses an asynchronous callback to return the result. **Permission required**: ohos.permission.READ_CONTACTS @@ -660,7 +656,6 @@ Queries contacts based on the specified key, application, and attributes. This A ```js contact.queryContact('xxx', { - holderId: 0 holderId: 0, bundleName: "", displayName: "" @@ -695,7 +690,6 @@ Queries contacts based on the specified key, application, and attributes. This A | attrs | [ContactAttributes](#contactattributes) | No | List of contact attributes. | **Return Value** - | Type | Description | | ---------------------------------- | ----------------------------------------------- | | Promise<[Contact](#contact)> | Promise used to return the result.| @@ -704,7 +698,6 @@ Queries contacts based on the specified key, application, and attributes. This A ```js let promise = contact.queryContact('xxx', { - holderId: 0 holderId: 0, bundleName: "", displayName: "" @@ -752,7 +745,7 @@ Queries all contacts. This API uses an asynchronous callback to return the resul queryContacts(holder: Holder, callback: AsyncCallback<Array<Contact>>): void -Queries all contacts based on the specified application. This API uses an asynchronous callback to return the result. +Queries all contacts. This API uses an asynchronous callback to return the result. **Permission required**: ohos.permission.READ_CONTACTS @@ -786,7 +779,7 @@ Queries all contacts based on the specified application. This API uses an asynch queryContacts(attrs: ContactAttributes, callback: AsyncCallback<Array<Contact>>): void -Queries all contacts based on the specified attributes. This API uses an asynchronous callback to return the result. +Queries all contacts. This API uses an asynchronous callback to return the result. **Permission required**: ohos.permission.READ_CONTACTS @@ -818,7 +811,7 @@ Queries all contacts based on the specified attributes. This API uses an asynchr queryContacts(holder: Holder, attrs: ContactAttributes, callback: AsyncCallback<Array<Contact>>): void -Queries all contacts based on the specified application and attributes. This API uses an asynchronous callback to return the result. +Queries all contacts. This API uses an asynchronous callback to return the result. **Permission required**: ohos.permission.READ_CONTACTS @@ -869,7 +862,6 @@ Queries all contacts based on the specified application and attributes. This API | attrs | [ContactAttributes](#contactattributes) | No | List of contact attributes. | **Return Value** - | Type | Description | | ----------------------------------------------- | --------------------------------------------------- | | Promise<Array<[Contact](#contact)>> | Promise used to return the result.| @@ -926,7 +918,7 @@ Queries contacts based on the specified phone number. This API uses an asynchron queryContactsByPhoneNumber(phoneNumber: string, holder: Holder, callback: AsyncCallback<Array<Contact>>): void -Queries contacts based on the specified phone number and application. This API uses an asynchronous callback to return the result. +Queries contacts based on the specified phone number. This API uses an asynchronous callback to return the result. **Permission required**: ohos.permission.READ_CONTACTS @@ -961,7 +953,7 @@ Queries contacts based on the specified phone number and application. This API u queryContactsByPhoneNumber(phoneNumber: string, attrs: ContactAttributes, callback: AsyncCallback<Array<Contact>>): void -Queries contacts based on the specified phone number and attributes. This API uses an asynchronous callback to return the result. +Queries contacts based on the specified phone number. This API uses an asynchronous callback to return the result. **Permission required**: ohos.permission.READ_CONTACTS @@ -994,7 +986,7 @@ Queries contacts based on the specified phone number and attributes. This API us queryContactsByPhoneNumber(phoneNumber: string, holder: Holder, attrs: ContactAttributes, callback: AsyncCallback<Array<Contact>>): void -Queries contacts based on the specified phone number, application, and attributes. This API uses an asynchronous callback to return the result. +Queries contacts based on the specified phone number. This API uses an asynchronous callback to return the result. **Permission required**: ohos.permission.READ_CONTACTS @@ -1104,7 +1096,7 @@ Queries contacts based on the specified email address. This API uses an asynchro queryContactsByEmail(email: string, holder: Holder, callback: AsyncCallback<Array<Contact>>): void -Queries contacts based on the specified email address and application. This API uses an asynchronous callback to return the result. +Queries contacts based on the specified email address. This API uses an asynchronous callback to return the result. **Permission required**: ohos.permission.READ_CONTACTS @@ -1122,7 +1114,7 @@ Queries contacts based on the specified email address and application. This API ```js contact.queryContactsByEmail('xxx@email.com', { - holderId: 0, + holderId: 0, bundleName: "", displayName: "" }, (err, data) => { @@ -1139,7 +1131,7 @@ Queries contacts based on the specified email address and application. This API queryContactsByEmail(email: string, attrs: ContactAttributes, callback: AsyncCallback<Array<Contact>>): void -Queries contacts based on the specified email address and attributes. This API uses an asynchronous callback to return the result. +Queries contacts based on the specified email address. This API uses an asynchronous callback to return the result. **Permission required**: ohos.permission.READ_CONTACTS @@ -1172,7 +1164,7 @@ Queries contacts based on the specified email address and attributes. This API u queryContactsByEmail(email: string, holder: Holder, attrs: ContactAttributes, callback: AsyncCallback<Array<Contact>>): void -Queries contacts based on the specified email address, application, and attributes. This API uses an asynchronous callback to return the result. +Queries contacts based on the specified email address. This API uses an asynchronous callback to return the result. **Permission required**: ohos.permission.READ_CONTACTS @@ -1281,7 +1273,7 @@ Queries all groups of this contact. This API uses an asynchronous callback to re queryGroups(holder: Holder, callback: AsyncCallback<Array<Group>>): void -Queries all groups of this contact based on the specified application. This API uses an asynchronous callback to return the result. +Queries all groups of this contact. This API uses an asynchronous callback to return the result. **Permission required**: ohos.permission.READ_CONTACTS @@ -1440,7 +1432,7 @@ Queries the key of a contact based on the specified contact ID. This API uses an queryKey(id: number, holder: Holder, callback: AsyncCallback<string>): void -Queries the key of a contact based on the specified contact ID and application. This API uses an asynchronous callback to return the result. +Queries the key of a contact based on the specified contact ID. This API uses an asynchronous callback to return the result. **Permission required**: ohos.permission.READ_CONTACTS @@ -1525,7 +1517,7 @@ Defines a contact. ### Attributes -| Name | Type | Readable| Writable| Description | +| Name | Type | Readable| Writable| Description | | ----------------- | --------------------------------------- | ---- | ---- | -------------------------------------- | | id | number | Yes | No | Contact ID. | | key | string | Yes | No | Contact key. | @@ -1587,7 +1579,7 @@ If **null** is passed, all attributes are queried by default. **System capability**: SystemCapability.Applications.ContactsData -| Name | Type | Readable| Writable| Description | +| Name | Type | Readable| Writable| Description | | ---------- | ------------------------- | ---- | ---- | ---------------- | | attributes | [Attribute](#attribute)[] | Yes | Yes | List of contact attributes.| @@ -1668,7 +1660,7 @@ Defines a contact's email. ### Attributes -| Name | Type| Readable| Writable| Description | +| Name | Type | Readable| Writable| Description | | ----------- | -------- | ---- | ---- | ---------------- | | email | string | Yes | Yes | Email addresses | | labelName | string | Yes | Yes | Name of the mailbox type.| @@ -1702,11 +1694,11 @@ Defines an application that creates the contact. **System capability**: SystemCapability.Applications.ContactsData -| Name | Type| Readable| Writable| Description | -| ----------- | -------- | ---- | ---- | ---------- | -| bundleName | string | Yes | No | Bundle name. | -| displayName | string | Yes | No | Application name.| -| holderId | number | Yes | Yes | Application ID. | +| Name | Type | Readable| Writable| Description | +| ----------- | ------ | ---- | ---- | ------------ | +| bundleName | string | Yes | No | Bundle name.| +| displayName | string | Yes | No | Application name. | +| holderId | number | Yes | Yes | Application ID. | **Example** @@ -1746,7 +1738,7 @@ Defines a contact's event. ### Attributes -| Name | Type| Readable| Writable| Description | +| Name | Type | Readable| Writable| Description | | --------- | -------- | ---- | ---- | -------------- | | eventDate | string | Yes | Yes | Event date. | | labelName | string | Yes | Yes | Event type.| @@ -1777,7 +1769,7 @@ Defines a contact group. **System capability**: SystemCapability.Applications.ContactsData -| Name | Type| Readable| Writable| Description | +| Name | Type | Readable| Writable| Description | | ------- | -------- | ---- | ---- | ------------------ | | groupId | number | Yes | Yes | ID of a contact group. | | title | string | Yes | Yes | Name of a contact group.| @@ -1825,7 +1817,7 @@ Enumerates IM addresses. ### Attributes -| Name | Type| Readable| Writable| Description | +| Name | Type | Readable| Writable| Description | | --------- | -------- | ---- | ---- | ------------------ | | imAddress | string | Yes | Yes | IM address. | | labelName | string | Yes | Yes | IM name.| @@ -1858,7 +1850,7 @@ Defines a contact's name. **System capability**: SystemCapability.Applications.ContactsData -| Name | Type| Readable| Writable| Description | +| Name | Type | Readable| Writable| Description | | ------------------ | -------- | ---- | ---- | --------------------------- | | familyName | string | Yes | Yes | Family name. | | familyNamePhonetic | string | Yes | Yes | Family name in pinyin. | @@ -1897,7 +1889,7 @@ Defines a contact's nickname. **System capability**: SystemCapability.Applications.ContactsData -| Name | Type| Readable| Writable| Description | +| Name | Type | Readable| Writable| Description | | -------- | -------- | ---- | ---- | -------------- | | nickName | string | Yes | Yes | Contact nickname.| @@ -1926,7 +1918,7 @@ Defines a contact's note. **System capability**: SystemCapability.Applications.ContactsData -| Name | Type| Readable| Writable| Description | +| Name | Type | Readable| Writable| Description | | ----------- | -------- | ---- | ---- | ------------------ | | noteContent | string | Yes | Yes | Notes of the contact.| @@ -1955,7 +1947,7 @@ Defines a contact's organization. **System capability**: SystemCapability.Applications.ContactsData -| Name | Type| Readable| Writable| Description | +| Name | Type | Readable| Writable| Description | | ----- | -------- | ---- | ---- | ---------- | | name | string | Yes | Yes | Organization name.| | title | string | Yes | Yes | Organization title.| @@ -2017,7 +2009,7 @@ Defines a contact's phone number. ### Attributes -| Name | Type| Readable| Writable| Description | +| Name | Type | Readable| Writable| Description | | ----------- | -------- | ---- | ---- | ------------------ | | labelName | string | Yes | Yes | Phone number type.| | phoneNumber | string | Yes | Yes | Phone number. | @@ -2049,7 +2041,7 @@ Defines a contact's portrait. **System capability**: SystemCapability.Applications.ContactsData -| Name| Type| Readable| Writable| Description | +| Name| Type | Readable| Writable| Description | | ---- | -------- | ---- | ---- | -------------- | | uri | string | Yes | Yes | Contact portrait.| @@ -2091,7 +2083,7 @@ Defines a contact's postal address. ### Attributes -| Name | Type| Readable| Writable| Description | +| Name | Type | Readable| Writable| Description | | ------------- | -------- | ---- | ---- | -------------------------- | | city | string | Yes | Yes | City where the contact is located. | | country | string | Yes | Yes | Country/Region where the contact is located. | @@ -2153,7 +2145,7 @@ Defines a contact's relationship. ### Attributes -| Name | Type| Readable| Writable| Description | +| Name | Type | Readable| Writable| Description | | ------------ | -------- | ---- | ---- | -------------- | | labelName | string | Yes | Yes | Relationship type.| | relationName | string | Yes | Yes | Relationship name. | @@ -2199,13 +2191,12 @@ Defines a contact's SIP address. ### Attributes -| Name | Type| Readable| Writable| Description | +| Name | Type | Readable| Writable| Description | | ---------- | -------- | ---- | ---- | --------------------------------- | | labelName | string | Yes | Yes | SIP address type.| | sipAddress | string | Yes | Yes | SIP address. | | labelId | number | Yes | Yes | SIP address ID. | - **Example** Create contact data in JSON format: @@ -2230,7 +2221,7 @@ Defines a contact's website. **System capability**: SystemCapability.Applications.ContactsData -| Name | Type| Readable| Writable| Description | +| Name | Type | Readable| Writable| Description | | ------- | -------- | ---- | ---- | ------------------ | | website | string | Yes | Yes | Website of the contact.| @@ -2250,4 +2241,4 @@ let website = { ```js let website = new contact.Website(); website.website = "website"; -``` \ No newline at end of file +``` diff --git a/en/application-dev/reference/apis/js-apis-http.md b/en/application-dev/reference/apis/js-apis-http.md index e884f1f348..1d0ef9bbc8 100644 --- a/en/application-dev/reference/apis/js-apis-http.md +++ b/en/application-dev/reference/apis/js-apis-http.md @@ -16,7 +16,7 @@ import http from '@ohos.net.http'; ## Examples ```js -// Import the HTTP namespace. +// Import the http namespace. import http from '@ohos.net.http'; // Each httpRequest corresponds to an HTTP request task and cannot be reused. @@ -112,7 +112,7 @@ Initiates an HTTP request to a given URL. This API uses an asynchronous callback **Error codes** -| ID | Error Message | +| Code | Error Message | |---------|-------------------------------------------------------| | 401 | Parameter error. | | 201 | Permission denied. | @@ -164,7 +164,7 @@ Initiates an HTTP request containing specified options to a given URL. This API **Error codes** -| ID | Error Message | +| Code | Error Message | |---------|-------------------------------------------------------| | 401 | Parameter error. | | 201 | Permission denied. | @@ -255,7 +255,7 @@ Initiates an HTTP request containing specified options to a given URL. This API **Error codes** -| ID | Error Message | +| Code | Error Message | |---------|-------------------------------------------------------| | 401 | Parameter error. | | 201 | Permission denied. | @@ -349,7 +349,7 @@ Initiates an HTTP request to a given URL. This API uses an asynchronous callback **Error codes** -| ID | Error Message | +| Code | Error Message | |---------|-------------------------------------------------------| | 401 | Parameter error. | | 201 | Permission denied. | @@ -395,7 +395,7 @@ Initiates an HTTP request to a given URL. This API uses an asynchronous callback **Error codes** -| ID | Error Message | +| Code | Error Message | |---------|-------------------------------------------------------| | 401 | Parameter error. | | 201 | Permission denied. | @@ -477,7 +477,7 @@ Initiates an HTTP request containing specified options to a given URL. This API **Error codes** -| ID | Error Message | +| Code | Error Message | |---------|-------------------------------------------------------| | 401 | Parameter error. | | 201 | Permission denied. | @@ -513,7 +513,7 @@ Initiates an HTTP request containing specified options to a given URL. This API >**NOTE** > For details about the error codes, see [HTTP Error Codes](../errorcodes/errorcode-net-http.md). -> The HTTP error code mapping is in the format of 2300000 + Curl error code. For more common error codes, see: +> The HTTP error code mapping is in the format of 2300000 + Curl error code. For more common error codes, see [Curl Error Codes](https://curl.se/libcurl/c/libcurl-errors.html). **Example** @@ -540,7 +540,7 @@ on(type: 'headerReceive', callback: AsyncCallback\): void Registers an observer for HTTP Response Header events. >**NOTE** ->This API has been deprecated. You are advised to use [on('headersReceive')8+](#onheadersreceive8) instead. +>This API has been deprecated. You are advised to use [on('headersReceive')8+](#onheadersreceive8). **System capability**: SystemCapability.Communication.NetStack @@ -567,7 +567,7 @@ Unregisters the observer for HTTP Response Header events. >**NOTE** > ->1. This API has been deprecated. You are advised to use [off('headersReceive')8+](#offheadersreceive8) instead. +>1. This API has been deprecated. You are advised to use [off('headersReceive')8+](#offheadersreceive8). > >2. You can pass the callback of the **on** function if you want to cancel listening for a certain type of event. If you do not pass the callback, you will cancel listening for all events. @@ -839,7 +839,7 @@ Enumerates the response codes for an HTTP request. | Name | Value | Description | | ----------------- | ---- | ------------------------------------------------------------ | -| OK | 200 | "OK." The request has been processed successfully. This return code is generally used for GET and POST requests. | +| OK | 200 | The request is successful. The request has been processed successfully. This return code is generally used for GET and POST requests. | | CREATED | 201 | "Created." The request has been successfully sent and a new resource is created. | | ACCEPTED | 202 | "Accepted." The request has been accepted, but the processing has not been completed. | | NOT_AUTHORITATIVE | 203 | "Non-Authoritative Information." The request is successful. | diff --git a/en/application-dev/reference/apis/js-apis-i18n.md b/en/application-dev/reference/apis/js-apis-i18n.md index 2a85da3460..db85444d68 100644 --- a/en/application-dev/reference/apis/js-apis-i18n.md +++ b/en/application-dev/reference/apis/js-apis-i18n.md @@ -2112,6 +2112,75 @@ Obtains the sequence of the year, month, and day in the specified locale. ``` +## Normalizer10+ + +### getInstance10+ + +static getInstance(mode: NormalizerMode): Normalizer + +Obtains a **Normalizer** object for text normalization. + +**System capability**: SystemCapability.Global.I18n + +**Parameters** + +| Name | Type | Mandatory | Description | +| ------ | ------ | ---- | ------------------------- | +| mode | [NormalizerMode](#normalizermode10) | Yes | Text normalization mode.| + +**Return value** + +| Type | Description | +| ------ | ------------------- | +| [Normalizer](#normalizer10) | **Normalizer** object for text normalization.| + +**Example** + ```js + let normalizer = I18n.Normalizer.getInstance(I18n.NormalizerMode.NFC); + ``` + + +### normalize10+ + +normalize(text: string): string + +Normalizes text strings. + +**System capability**: SystemCapability.Global.I18n + +**Parameters** + +| Name | Type | Mandatory | Description | +| ------ | ------ | ---- | ------------------------- | +| text | string | Yes | Text strings to be normalized.| + +**Return value** + +| Type | Description | +| ------ | ------------------- | +| string | Normalized text strings.| + +**Example** + ```js + let normalizer = I18n.Normalizer.getInstance(I18n.NormalizerMode.NFC); + let normalizedText = normalizer.normalize('\u1E9B\u0323'); // normalizedText = \u1E9B\u0323 + ``` + + +## NormalizerMode10+ + +Enumerates text normalization modes. + +**System capability**: SystemCapability.Global.I18n + +| Name| Value| Description| +| -------- | -------- | -------- | +| NFC | 1 | NFC.| +| NFD | 2 | NFD.| +| NFKC | 3 | NFKC.| +| NFKD | 4 | NFKD.| + + ## I18n.getDisplayCountry(deprecated) getDisplayCountry(country: string, locale: string, sentenceCase?: boolean): string diff --git a/en/application-dev/reference/apis/js-apis-net-mdns.md b/en/application-dev/reference/apis/js-apis-net-mdns.md new file mode 100644 index 0000000000..b2e157c03a --- /dev/null +++ b/en/application-dev/reference/apis/js-apis-net-mdns.md @@ -0,0 +1,551 @@ +# @ohos.net.mdns (mDNS Management) + +Multicast DNS (mDNS) provides functions such as adding, removing, discovering, and resolving local services on a LAN. + +> **NOTE** +> The initial APIs of this module are supported since API version 10. Newly added APIs will be marked with a superscript to indicate their earliest API version. + +## Modules to Import + +```js +import mdns from '@ohos.net.mdns' +``` +## mdns.addLocalService + +addLocalService(context: Context, serviceInfo: LocalServiceInfo, callback: AsyncCallback\): void + +Adds an mDNS service. This API uses an asynchronous callback to return the result. + +**System capability**: SystemCapability.Communication.NetManager.MDNS + +**Parameters** + +| Name | Type | Mandatory| Description | +|-------------|----------------------------------|-----------|-------------------------------------------------| +| context | Context | Yes | Application context.
For details about the application context of the FA model, see [Context](js-apis-inner-app-context.md).
For details about the application context of the stage model, see [Context](js-apis-inner-application-uiAbilityContext.md).| +| serviceInfo | [LocalServiceInfo](#localserviceinfo) | Yes | mDNS service information. | +| callback | AsyncCallback\<[LocalServiceInfo](#localserviceinfo)> | Yes | Callback used to return the result. If the operation is successful, **error** is **undefined** and **data** is the mDNS service information. | + +**Error codes** + +| ID | Error Message| +|---------|---| +| 401 | Parameter error. | +| 2100002 | Operation failed. Cannot connect to service. | +| 2100003 | System internal error. | +| 2204003 | Callback duplicated. | +| 2204008 | Service instance duplicated. | +| 2204010 | Send packet failed. | + +>**NOTE** +> For details about the error codes, see [mDNS Error Codes](../errorcodes/errorcode-net-mdns.md). + +**Example** + +```js +let localServiceInfo = { + serviceType: "_print._tcp", + serviceName: "servicename", + port: 5555, + host: { + address: "10.14.**.***", + }, + serviceAttribute: [{ + key: "111", + value: [1] + }] +} + +mdns.addLocalService(context, localServiceInfo, function (error, data) { + console.log(JSON.stringify(error)) + console.log(JSON.stringify(data)) +}); +``` + +## mdns.addLocalService + +addLocalService(context: Context, serviceInfo: LocalServiceInfo): Promise\ + +Adds an mDNS service. This API uses a promise to return the result. + +**System capability**: SystemCapability.Communication.NetManager.MDNS + +**Parameters** + +| Name | Type | Mandatory| Description | +|-------------|----------------------------------|-----------|-------------------------------------------------| +| context | Context | Yes | Application context.
For details about the application context of the FA model, see [Context](js-apis-inner-app-context.md).
For details about the application context of the stage model, see [Context](js-apis-inner-application-uiAbilityContext.md).| +| serviceInfo | [LocalServiceInfo](#localserviceinfo) | Yes | mDNS service information. | + +**Return value** + +| Type | Description | +| --------------------------------- | ------------------------------------- | +| Promise\<[LocalServiceInfo](#localserviceinfo)> | Promise used to return the result.| + +**Error codes** + +| ID | Error Message| +|---------|---| +| 401 | Parameter error. | +| 2100002 | Operation failed. Cannot connect to service. | +| 2100003 | System internal error. | +| 2204003 | Callback duplicated. | +| 2204008 | Service instance duplicated. | +| 2204010 | Send packet failed. | + +>**NOTE** +> For details about the error codes, see [mDNS Error Codes](../errorcodes/errorcode-net-mdns.md). + +**Example** + +```js +let localServiceInfo = { + serviceType: "_print._tcp", + serviceName: "servicename", + port: 5555, + host: { + address: "10.14.**.***", + }, + serviceAttribute: [{ + key: "111", + value: [1] + }] +} + +mdns.addLocalService(context, localServiceInfo).then(function (data) { + console.log(JSON.stringify(data)) +}); +``` + +## mdns.removeLocalService + +removeLocalService(context: Context, serviceInfo: LocalServiceInfo, callback: AsyncCallback\): void + +Removes an mDNS service. This API uses an asynchronous callback to return the result. + +**System capability**: SystemCapability.Communication.NetManager.MDNS + +**Parameters** + +| Name | Type | Mandatory| Description | +|-------------|----------------------------------|-----------|-------------------------------------------------| +| context | Context | Yes | Application context.
For details about the application context of the FA model, see [Context](js-apis-inner-app-context.md).
For details about the application context of the stage model, see [Context](js-apis-inner-application-uiAbilityContext.md).| +| serviceInfo | [LocalServiceInfo](#localserviceinfo) | Yes | mDNS service information. | +| callback | AsyncCallback\<[LocalServiceInfo](#localserviceinfo)> | Yes | Callback used to return the result. If the operation is successful, **error** is **undefined** and **data** is the mDNS service information. | + +**Error codes** + +| ID | Error Message| +|---------|---| +| 401 | Parameter error. | +| 2100002 | Operation failed. Cannot connect to service. | +| 2100003 | System internal error. | +| 2204002 | Callback not found. | +| 2204008 | Service instance duplicated. | +| 2204010 | Send packet failed. | + +>**NOTE** +> For details about the error codes, see [mDNS Error Codes](../errorcodes/errorcode-net-mdns.md). + +**Example** + +```js +let localServiceInfo = { + serviceType: "_print._tcp", + serviceName: "servicename", + port: 5555, + host: { + address: "10.14.**.***", + }, + serviceAttribute: [{ + key: "111", + value: [1] + }] +} + +mdns.removeLocalService(context, localServiceInfo, function (error, data) { + console.log(JSON.stringify(error)) + console.log(JSON.stringify(data)) +}); +``` + +## mdns.removeLocalService + +removeLocalService(context: Context, serviceInfo: LocalServiceInfo): Promise\ + +Removes an mDNS service. This API uses a promise to return the result. + +**System capability**: SystemCapability.Communication.NetManager.MDNS + +**Parameters** + +| Name | Type | Mandatory| Description | +|-------------|----------------------------------|-----------|-------------------------------------------------| +| context | Context | Yes | Application context.
For details about the application context of the FA model, see [Context](js-apis-inner-app-context.md).
For details about the application context of the stage model, see [Context](js-apis-inner-application-uiAbilityContext.md).| +| serviceInfo | [LocalServiceInfo](#localserviceinfo) | Yes | mDNS service information. | + +**Return value** + +| Type | Description | +| --------------------------------- | ------------------------------------- | +| Promise\<[LocalServiceInfo](#localserviceinfo)> | Promise used to return the result.| + +**Error codes** + +| ID | Error Message| +|---------|---| +| 401 | Parameter error. | +| 2100002 | Operation failed. Cannot connect to service. | +| 2100003 | System internal error. | +| 2204002 | Callback not found. | +| 2204008 | Service instance duplicated. | +| 2204010 | Send packet failed. | + +>**NOTE** +> For details about the error codes, see [mDNS Error Codes](../errorcodes/errorcode-net-mdns.md). + +**Example** + +```js +let localServiceInfo = { + serviceType: "_print._tcp", + serviceName: "servicename", + port: 5555, + host: { + address: "10.14.**.***", + }, + serviceAttribute: [{ + key: "111", + value: [1] + }] +} + +mdns.removeLocalService(context, localServiceInfo).then(function (data) { + console.log(JSON.stringify(data)) +}); +``` + +## mdns.createDiscoveryService + +createDiscoveryService(context: Context, serviceType: string): DiscoveryService + +Creates a **DiscoveryService** object, which is used to discover mDNS services of the specified type. + +**System capability**: SystemCapability.Communication.NetManager.MDNS + +**Parameters** + +| Name | Type | Mandatory| Description | +|-------------|---------|-----------| ------------------------------------------------------------ | +| context | Context | Yes | Application context.
For details about the application context of the FA model, see [Context](js-apis-inner-app-context.md).
For details about the application context of the stage model, see [Context](js-apis-inner-application-uiAbilityContext.md).| +| serviceType | string | Yes | Type of the mDNS services to be discovered.| + +**Return value** + +| Type | Description | +| ----------------------------- |---------------------------------| +| DiscoveryService | **DiscoveryService** object used to discover mDNS services of the specified type.| + +**Example** + +```js +let serviceType = "_print._tcp"; + +let discoveryService = mdns.createDiscoveryService(context, serviceType); +``` + +## mdns.resolveLocalService + +resolveLocalService(context: Context, serviceInfo: LocalServiceInfo, callback: AsyncCallback\): void + +Resolves an mDNS service. This API uses an asynchronous callback to return the result. + +**System capability**: SystemCapability.Communication.NetManager.MDNS + +**Parameters** + +| Name | Type | Mandatory| Description | +|-------------|----------------------------------|-----------|-------------------------------------------------------------| +| context | Context | Yes | Application context.
For details about the application context of the FA model, see [Context](js-apis-inner-app-context.md).
For details about the application context of the stage model, see [Context](js-apis-inner-application-uiAbilityContext.md).| +| serviceInfo | [LocalServiceInfo](#localserviceinfo) | Yes | mDNS service information. | +| callback | AsyncCallback\<[LocalServiceInfo](#localserviceinfo)> | Yes | Callback used to return the result. If the operation is successful, **error** is **undefined** and **data** is the mDNS service information. | + +**Error codes** + +| ID | Error Message| +|---------|----------------------------------------------| +| 401 | Parameter error. | +| 2100002 | Operation failed. Cannot connect to service. | +| 2100003 | System internal error. | +| 2204003 | Callback duplicated. | +| 2204006 | Request timeout. | +| 2204010 | Send packet failed. | + +>**NOTE** +> For details about the error codes, see [mDNS Error Codes](../errorcodes/errorcode-net-mdns.md). + +**Example** + +```js +let localServiceInfo = { + serviceType: "_print._tcp", + serviceName: "servicename", + port: 5555, + host: { + address: "10.14.**.***", + }, + serviceAttribute: [{ + key: "111", + value: [1] + }] +} + +mdns.resolveLocalService(context, localServiceInfo, function (error, data) { + console.log(JSON.stringify(error)) + console.log(JSON.stringify(data)) +}); +``` + +## mdns.resolveLocalService + +resolveLocalService(context: Context, serviceInfo: LocalServiceInfo): Promise\ + +Resolves an mDNS service. This API uses a promise to return the result. + +**System capability**: SystemCapability.Communication.NetManager.MDNS + +**Parameters** + +| Name | Type | Mandatory| Description | +|-------------|--------------|-----------|-----------------------------------------------------| +| context | Context | Yes | Application context.
For details about the application context of the FA model, see [Context](js-apis-inner-app-context.md).
For details about the application context of the stage model, see [Context](js-apis-inner-application-uiAbilityContext.md).| +| serviceInfo | [LocalServiceInfo](#localserviceinfo) | Yes | mDNS service information. | + +**Return value** + +| Type | Description | +|----------------------------| ------------------------------------- | +| Promise\<[LocalServiceInfo](#localserviceinfo)> | Promise used to return the result.| + +**Error codes** + +| ID | Error Message| +|---------|----------------------------------------------| +| 401 | Parameter error. | +| 2100002 | Operation failed. Cannot connect to service. | +| 2100003 | System internal error. | +| 2204003 | Callback duplicated. | +| 2204006 | Request timeout. | +| 2204010 | Send packet failed. | + +>**NOTE** +> For details about the error codes, see [mDNS Error Codes](../errorcodes/errorcode-net-mdns.md). + +**Example** + +```js +let localServiceInfo = { + serviceType: "_print._tcp", + serviceName: "servicename", + port: 5555, + host: { + address: "10.14.**.***", + }, + serviceAttribute: [{ + key: "111", + value: [1] + }] +} + +mdns.resolveLocalService(context, localServiceInfo).then(function (data){ + console.log(JSON.stringify(data)); +}) +``` + +## DiscoveryService + +Defines a **DiscoveryService** object for discovering mDNS services of the specified type. + +### startSearchingMDNS + +startSearchingMDNS(): void + +Searches for mDNS services on the LAN. + +**System capability**: SystemCapability.Communication.NetManager.MDNS + +**Example** + +```js +let discoveryService = mdns.createDiscoveryService(context, serviceType); +discoveryService.startSearchingMDNS(); +``` + +### stopSearchingMDNS + +stopSearchingMDNS(): void + +Stops searching for mDNS services on the LAN. + +**System capability**: SystemCapability.Communication.NetManager.MDNS + +**Example** + +```js +let discoveryService = mdns.createDiscoveryService(context, serviceType); +discoveryService.stopSearchingMDNS(); +``` + +### on('discoveryStart') + +on(type: 'discoveryStart', callback: Callback<{serviceInfo: LocalServiceInfo, errorCode?: MDNS_ERR}>): void + +Enables listening for **discoveryStart** events. + +**System capability**: SystemCapability.Communication.NetManager.MDNS + +**Parameters** + +| Name | Type | Mandatory| Description | +|-------------|--------------|-----------|-----------------------------------------------------| +| type | string | Yes |Event type. This field has a fixed value of **discoveryStart**.
**discoveryStart**: event of starting discovery of mDNS services on the LAN.| +| callback | Callback<{serviceInfo: [LocalServiceInfo](#localserviceinfo), errorCode?: [MDNS_ERR](#mdns_err)}> | Yes | Callback used to return the mDNS service and error information. | + +**Example** + +```js +// See mdns.createDiscoveryService. +let discoveryService = mdns.createDiscoveryService(context, serviceType); +discoveryService.startSearchingMDNS(); + +discoveryService.on('discoveryStart', (data) => { + console.log(JSON.stringify(data)); +}); + +discoveryService.stopSearchingMDNS(); +``` + +### on('discoveryStop') + +on(type: 'discoveryStop', callback: Callback<{serviceInfo: LocalServiceInfo, errorCode?: MDNS_ERR}>): void + +Enables listening for **discoveryStop** events. + +**System capability**: SystemCapability.Communication.NetManager.MDNS + +**Parameters** + +| Name | Type | Mandatory| Description | +|-------------|--------------|-----------|-----------------------------------------------------| +| type | string | Yes |Event type. This field has a fixed value of **discoveryStop**.
**discoveryStop**: event of stopping discovery of mDNS services on the LAN.| +| callback | Callback<{serviceInfo: [LocalServiceInfo](#localserviceinfo), errorCode?: [MDNS_ERR](#mdns_err)}> | Yes | Callback used to return the mDNS service and error information. | + +**Example** + +```js +// See mdns.createDiscoveryService. +let discoveryService = mdns.createDiscoveryService(context, serviceType); +discoveryService.startSearchingMDNS(); + +discoveryService.on('discoveryStop', (data) => { + console.log(JSON.stringify(data)); +}); + +discoveryService.stopSearchingMDNS(); +``` + +### on('serviceFound') + +on(type: 'serviceFound', callback: Callback<[LocalServiceInfo](#localserviceinfo)>): void + +Enables listening for **serviceFound** events. + +**System capability**: SystemCapability.Communication.NetManager.MDNS + +**Parameters** + +| Name | Type | Mandatory| Description | +|-------------|--------------|-----------|-----------------------------------------------------| +| type | string | Yes |Event type. This field has a fixed value of **serviceFound**.
**serviceFound**: event indicating an mDNS service is found.| +| callback | Callback<[LocalServiceInfo](#localserviceinfo)> | Yes | mDNS service information. | + +**Example** + +```js +// See mdns.createDiscoveryService. +let discoveryService = mdns.createDiscoveryService(context, serviceType); +discoveryService.startSearchingMDNS(); + +discoveryService.on('serviceFound', (data) => { + console.log(JSON.stringify(data)); +}); + +discoveryService.stopSearchingMDNS(); +``` + +### on('serviceLost') + +on(type: 'serviceLost', callback: Callback<[LocalServiceInfo](#localserviceinfo)>): void + +Enables listening for **serviceLost** events. + +**System capability**: SystemCapability.Communication.NetManager.MDNS + +**Parameters** + +| Name | Type | Mandatory| Description | +|-------------|--------------|-----------|-----------------------------------------------------| +| type | string | Yes |Event type. This field has a fixed value of **serviceLost**.
serviceLost: event indicating that an mDNS service is removed.| +| callback | Callback<[LocalServiceInfo](#localserviceinfo)> | Yes | mDNS service information. | + +**Example** + +```js +// See mdns.createDiscoveryService. +let discoveryService = mdns.createDiscoveryService(context, serviceType); +discoveryService.startSearchingMDNS(); + +discoveryService.on('serviceLost', (data) => { + console.log(JSON.stringify(data)); +}); + +discoveryService.stopSearchingMDNS(); +``` + +## LocalServiceInfo + +Defines the mDNS service information. + +**System capability**: SystemCapability.Communication.NetManager.MDNS + +| Name | Type | Mandatory| Description | +| --------------------- | ---------------------------------- | --- | ------------------------ | +| serviceType | string | Yes| Type of the mDNS service. The value is in the format of **\_\.\**, where **name** contains a maximum of 63 characters excluding periods (.). | +| serviceName | string | Yes| Name of the mDNS service. | +| port | number | No| Port number of the mDNS server. | +| host | [NetAddress](js-apis-net-connection.md#netaddress) | No| IP address of the device that provides the mDNS service. The IP address is not effective when an mDNS service is added or removed. | +| serviceAttribute | serviceAttribute\<[ServiceAttribute](#serviceattribute)> | No| mDNS service attribute information. | + +## ServiceAttribute + +Defines the mDNS service attribute information. + +**System capability**: SystemCapability.Communication.NetManager.MDNS + +| Name | Type | Mandatory| Description | +| --------------------- | ---------------------------------- | --- | ------------------------ | +| key | string | Yes| mDNS service attribute key. The value contains a maximum of 9 characters. | +| value | Array\ | Yes| mDNS service attribute value. | + +## MDNS_ERR + +Defines the mDNS error information. + +**System capability**: SystemCapability.Communication.NetManager.MDNS + +| Name | Value | Description | +| --------------- | ---- | ----------- | +| INTERNAL_ERROR | 0 | Operation failed because of an internal error. | +| ALREADY_ACTIVE | 1 | Operation failed because the service already exists.| +| MAX_LIMIT | 2 | Operation failed because the number of requests exceeds the maximum value. (not supported currently)| diff --git a/en/application-dev/reference/apis/js-apis-power.md b/en/application-dev/reference/apis/js-apis-power.md index e8215f250a..f98e56905a 100644 --- a/en/application-dev/reference/apis/js-apis-power.md +++ b/en/application-dev/reference/apis/js-apis-power.md @@ -1,8 +1,9 @@ -# @ohos.power (System Power Management) +# @ohos.power (Power Manager) The **power** module provides APIs for rebooting and shutting down the system, as well as querying the screen status. -> **NOTE**
+> **NOTE** +> > The initial APIs of this module are supported since API version 7. Newly added APIs will be marked with a superscript to indicate their earliest API version. ## Modules to Import @@ -33,7 +34,7 @@ Shuts down the system. For details about the error codes, see [Power Manager Error Codes](../errorcodes/errorcode-power.md). -| Code | Error Message | +| ID | Error Message | |---------|---------| | 4900101 | Operation failed. Cannot connect to service.| @@ -69,7 +70,7 @@ Reboots the system. For details about the error codes, see [Power Manager Error Codes](../errorcodes/errorcode-power.md). -| Code | Error Message | +| ID | Error Message | |---------|---------| | 4900101 | Operation failed. Cannot connect to service.| @@ -95,7 +96,7 @@ Checks whether the current device is active. In the active state, the screen is For details about the error codes, see [Power Manager Error Codes](../errorcodes/errorcode-power.md). -| Code | Error Message | +| ID | Error Message | |---------|---------| | 4900101 | Operation failed. Cannot connect to service.| @@ -130,7 +131,7 @@ Wakes up a device. For details about the error codes, see [Power Manager Error Codes](../errorcodes/errorcode-power.md). -| Code | Error Message | +| ID | Error Message | |---------|---------| | 4900101 | Operation failed. Cannot connect to service.| @@ -158,7 +159,7 @@ Hibernates a device. For details about the error codes, see [Power Manager Error Codes](../errorcodes/errorcode-power.md). -| Code | Error Message | +| ID | Error Message | |---------|---------| | 4900101 | Operation failed. Cannot connect to service.| @@ -190,7 +191,7 @@ Obtains the power mode of this device. For details about the error codes, see [Power Manager Error Codes](../errorcodes/errorcode-power.md). -| Code | Error Message | +| ID | Error Message | |---------|---------| | 4900101 | Operation failed. Cannot connect to service.| @@ -228,7 +229,7 @@ Sets the power mode of this device. This API uses an asynchronous callback to re For details about the error codes, see [Power Manager Error Codes](../errorcodes/errorcode-power.md). -| Code | Error Message | +| ID | Error Message | |---------|---------| | 4900101 | Operation failed. Cannot connect to service.| @@ -272,7 +273,7 @@ Sets the power mode of this device. This API uses a promise to return the result For details about the error codes, see [Power Manager Error Codes](../errorcodes/errorcode-power.md). -| Code | Error Message | +| ID | Error Message | |---------|---------| | 4900101 | Operation failed. Cannot connect to service.| @@ -292,8 +293,7 @@ power.setPowerMode(power.DevicePowerMode.MODE_PERFORMANCE) rebootDevice(reason: string): void -> NOTE
-> This API is deprecated since API version 9. You are advised to use [power.reboot](#powerreboot9) instead. +> **NOTE**
This API is supported since API version 7 and is deprecated since API version 9. You are advised to use [power.reboot](#powerreboot9). The substitute API is available only for system applications. Reboots the system. @@ -317,8 +317,7 @@ power.rebootDevice('reboot_test'); isScreenOn(callback: AsyncCallback<boolean>): void -> NOTE
-> This API is deprecated since API version 9. You are advised to use [power.isActive](#powerisactive9) instead. +> **NOTE**
This API is deprecated since API version 9. You are advised to use [power.isActive](#powerisactive9). Checks the screen status of the current device. This API uses an asynchronous callback to return the result. @@ -328,7 +327,7 @@ Checks the screen status of the current device. This API uses an asynchronous ca | Name | Type | Mandatory| Description | | -------- | ---------------------------- | ---- | ------------------------------------------------------------ | -| callback | AsyncCallback<boolean> | Yes | Callback used to return the result. If the operation is successful, **err** is **undefined** and **data** is the screen status obtained, where the value **true** indicates on and the value **false** indicates the opposite. Otherwise, **err** is an error object.| +| callback | AsyncCallback<boolean> | Yes | Callback used to return the result. If the operation is successful, **err** is **undefined** and **data** is the screen status obtained, where the value **true** indicates on and the value **false** indicates off. Otherwise, **err** is an error object.| **Example** @@ -346,8 +345,7 @@ power.isScreenOn((err, data) => { isScreenOn(): Promise<boolean> -> NOTE
-> This API is deprecated since API version 9. You are advised to use [power.isActive](#powerisactive9) instead. +> **NOTE**
This API is deprecated since API version 9. You are advised to use [power.isActive](#powerisactive9). Checks the screen status of the current device. This API uses a promise to return the result. diff --git a/en/application-dev/reference/apis/js-apis-system-brightness.md b/en/application-dev/reference/apis/js-apis-system-brightness.md index 3cc0779edf..8053c8f0c7 100644 --- a/en/application-dev/reference/apis/js-apis-system-brightness.md +++ b/en/application-dev/reference/apis/js-apis-system-brightness.md @@ -3,7 +3,8 @@ The **brightness** module provides APIs for querying and adjusting the screen brightness and mode. > **NOTE** -> - The APIs of this module are no longer maintained since API version 7. It is recommended that you use [`@ohos.brightness`](js-apis-brightness.md) instead. +> +> - The APIs of this module are no longer maintained since API version 7. You are advised to use APIs of [`@ohos.brightness`](js-apis-brightness.md). The substitute APIs are available only for system applications. > - The initial APIs of this module are supported since API version 3. Newly added APIs will be marked with a superscript to indicate their earliest API version. diff --git a/en/application-dev/reference/apis/js-apis-telephony-data.md b/en/application-dev/reference/apis/js-apis-telephony-data.md index 7e24457414..a7a1338277 100644 --- a/en/application-dev/reference/apis/js-apis-telephony-data.md +++ b/en/application-dev/reference/apis/js-apis-telephony-data.md @@ -1,6 +1,6 @@ # @ohos.telephony.data (Cellular Data) -The cellular data module provides basic mobile data management functions. You can obtain and set the default slot of the SIM card used for mobile data, and obtain the uplink and downlink connection status of cellular data services and connection status of the packet switched (PS) domain. Besides, you can check whether cellular data services and data roaming are enabled. +The **data** module provides basic mobile data management functions. You can obtain and set the default slot of the SIM card used for mobile data, and obtain the uplink and downlink connection status of cellular data services and connection status of the packet switched (PS) domain. Besides, you can check whether cellular data services and data roaming are enabled. >**NOTE** > @@ -24,7 +24,7 @@ Obtains the default slot of the SIM card used for mobile data. This API uses an | Name | Type | Mandatory| Description | | -------- | ----------------------- | ---- | ------------------------------------------ | -| callback | AsyncCallback\ | Yes | Callback used to return the result.
**0**: card slot 1
**1**: card slot 2| +| callback | AsyncCallback\ | Yes | Callback used to return the result.
**0**: card slot 1.
**1**: card slot 2.| **Example** @@ -46,7 +46,7 @@ Obtains the default slot of the SIM card used for mobile data. This API uses a p | Type | Description | | ----------------- | ------------------------------------------------------------ | -| Promise\ | Promise used to return the result.
**0**: card slot 1
**1**: card slot 2| +| Promise\ | Promise used to return the result.
**0**: card slot 1.
**1**: card slot 2.| **Example** @@ -71,7 +71,7 @@ Obtains the default SIM card used for mobile data synchronously. | Type | Description | | ------ | -------------------------------------------------- | -| number | Card slot ID.
**0**: card slot 1
**1**: card slot 2| +| number | Card slot ID.
**0**: card slot 1.
**1**: card slot 2.| **Example** @@ -87,7 +87,7 @@ Sets the default slot of the SIM card used for mobile data. This API uses an asy **System API**: This is a system API. -**Required permission**: ohos.permission.SET_TELEPHONY_STATE +**Required permissions**: ohos.permission.SET_TELEPHONY_STATE **System capability**: SystemCapability.Telephony.CellularData @@ -95,7 +95,7 @@ Sets the default slot of the SIM card used for mobile data. This API uses an asy | Name | Type | Mandatory| Description | | -------- | --------------------- | ---- | ------------------------------------------------------------ | -| slotId | number | Yes | SIM card slot ID.
**0**: card slot 1
**1**: card slot 2
**-1**: Clears the default configuration.| +| slotId | number | Yes | SIM card slot ID.
**0**: card slot 1.
**1**: card slot 2.
**-1**: Clears the default configuration.| | callback | AsyncCallback\ | Yes | Callback used to return the result. | **Error codes** @@ -129,7 +129,7 @@ Sets the default slot of the SIM card used for mobile data. This API uses a prom **System API**: This is a system API. -**Required permission**: ohos.permission.SET_TELEPHONY_STATE +**Required permissions**: ohos.permission.SET_TELEPHONY_STATE **System capability**: SystemCapability.Telephony.CellularData @@ -137,7 +137,7 @@ Sets the default slot of the SIM card used for mobile data. This API uses a prom | Name| Type | Mandatory| Description | | ------ | ------ | ---- | ------------------------------------------------------------ | -| slotId | number | Yes | SIM card slot ID.
**0**: card slot 1
**1**: card slot 2
**-1**: Clears the default configuration.| +| slotId | number | Yes | SIM card slot ID.
**0**: card slot 1.
**1**: card slot 2.
**-1**: Clears the default configuration.| **Return value** @@ -356,7 +356,7 @@ Checks whether roaming is enabled for the cellular data service. This API uses a | Name | Type | Mandatory| Description | | -------- | ------------------------ | ---- | ------------------------------------------------------------ | -| slotId | number | Yes | Card slot ID.
**0**: card slot 1
**1**: card slot 2 | +| slotId | number | Yes | Card slot ID.
**0**: card slot 1.
**1**: card slot 2. | | callback | AsyncCallback\ | Yes | Callback used to return the result.
**true**: Roaming is enabled for the cellular data service.
**false**: Roaming is disabled for the cellular data service.| **Error codes** @@ -394,7 +394,7 @@ Checks whether roaming is enabled for the cellular data service. This API uses a | Name| Type | Mandatory| Description | | ------ | ------ | ---- | ---------------------------------------- | -| slotId | number | Yes | Card slot ID.
**0**: card slot 1
**1**: card slot 2| +| slotId | number | Yes | Card slot ID.
**0**: card slot 1.
**1**: card slot 2.| **Return value** @@ -434,7 +434,7 @@ Enables the cellular data service. This API uses an asynchronous callback to ret **System API**: This is a system API. -**Required permission**: ohos.permission.SET_TELEPHONY_STATE +**Required permissions**: ohos.permission.SET_TELEPHONY_STATE **System capability**: SystemCapability.Telephony.CellularData @@ -473,7 +473,7 @@ Enables the cellular data service. This API uses a promise to return the result. **System API**: This is a system API. -**Required permission**: ohos.permission.SET_TELEPHONY_STATE +**Required permissions**: ohos.permission.SET_TELEPHONY_STATE **System capability**: SystemCapability.Telephony.CellularData @@ -515,7 +515,7 @@ Disables the cellular data service. This API uses an asynchronous callback to re **System API**: This is a system API. -**Required permission**: ohos.permission.SET_TELEPHONY_STATE +**Required permissions**: ohos.permission.SET_TELEPHONY_STATE **System capability**: SystemCapability.Telephony.CellularData @@ -554,7 +554,7 @@ Disables the cellular data service. This API uses a promise to return the result **System API**: This is a system API. -**Required permission**: ohos.permission.SET_TELEPHONY_STATE +**Required permissions**: ohos.permission.SET_TELEPHONY_STATE **System capability**: SystemCapability.Telephony.CellularData @@ -596,7 +596,7 @@ Enables the cellular data roaming service. This API uses an asynchronous callbac **System API**: This is a system API. -**Required permission**: ohos.permission.SET_TELEPHONY_STATE +**Required permissions**: ohos.permission.SET_TELEPHONY_STATE **System capability**: SystemCapability.Telephony.CellularData @@ -604,7 +604,7 @@ Enables the cellular data roaming service. This API uses an asynchronous callbac | Name | Type | Mandatory| Description | | -------- | --------------------- | ---- | ---------------------------------------- | -| slotId | number | Yes | Card slot ID.
**0**: card slot 1
**1**: card slot 2| +| slotId | number | Yes | Card slot ID.
**0**: card slot 1.
**1**: card slot 2.| | callback | AsyncCallback\ | Yes | Callback used to return the result. | **Error codes** @@ -636,7 +636,7 @@ Enables the cellular data roaming service. This API uses a promise to return the **System API**: This is a system API. -**Required permission**: ohos.permission.SET_TELEPHONY_STATE +**Required permissions**: ohos.permission.SET_TELEPHONY_STATE **System capability**: SystemCapability.Telephony.CellularData @@ -644,7 +644,7 @@ Enables the cellular data roaming service. This API uses a promise to return the | Name| Type | Mandatory| Description | | ------ | ------ | ---- | ---------------------------------------- | -| slotId | number | Yes | Card slot ID.
**0**: card slot 1
**1**: card slot 2| +| slotId | number | Yes | Card slot ID.
**0**: card slot 1.
**1**: card slot 2.| **Return value** @@ -684,7 +684,7 @@ Disables the cellular data roaming service. This API uses an asynchronous callba **System API**: This is a system API. -**Required permission**: ohos.permission.SET_TELEPHONY_STATE +**Required permissions**: ohos.permission.SET_TELEPHONY_STATE **System capability**: SystemCapability.Telephony.CellularData @@ -692,7 +692,7 @@ Disables the cellular data roaming service. This API uses an asynchronous callba | Name | Type | Mandatory| Description | | -------- | --------------------- | ---- | ---------------------------------------- | -| slotId | number | Yes | Card slot ID.
**0**: card slot 1
**1**: card slot 2| +| slotId | number | Yes | Card slot ID.
**0**: card slot 1.
**1**: card slot 2.| | callback | AsyncCallback\ | Yes | Callback used to return the result. | **Error codes** @@ -724,7 +724,7 @@ Disables the cellular data roaming service. This API uses a promise to return th **System API**: This is a system API. -**Required permission**: ohos.permission.SET_TELEPHONY_STATE +**Required permissions**: ohos.permission.SET_TELEPHONY_STATE **System capability**: SystemCapability.Telephony.CellularData @@ -732,7 +732,7 @@ Disables the cellular data roaming service. This API uses a promise to return th | Name| Type | Mandatory| Description | | ------ | ------ | ---- | ---------------------------------------- | -| slotId | number | Yes | Card slot ID.
**0**: card slot 1
**1**: card slot 2| +| slotId | number | Yes | Card slot ID.
**0**: card slot 1.
**1**: card slot 2.| **Return value** diff --git a/en/application-dev/reference/errorcodes/Readme-EN.md b/en/application-dev/reference/errorcodes/Readme-EN.md index 769c7d3905..260820d120 100644 --- a/en/application-dev/reference/errorcodes/Readme-EN.md +++ b/en/application-dev/reference/errorcodes/Readme-EN.md @@ -56,6 +56,7 @@ - [Ethernet Connection Error Codes](errorcode-net-ethernet.md) - [Network Sharing Error Codes](errorcode-net-sharing.md) - [Policy Management Error Codes](errorcode-net-policy.md) + - [mDNS Error Codes](errorcode-net-mdns.md) - Connectivity - [Bluetooth Error Codes](errorcode-bluetoothManager.md) - [Wi-Fi Error Codes](errorcode-wifi.md) diff --git a/en/application-dev/reference/errorcodes/errorcode-net-mdns.md b/en/application-dev/reference/errorcodes/errorcode-net-mdns.md new file mode 100644 index 0000000000..c174765757 --- /dev/null +++ b/en/application-dev/reference/errorcodes/errorcode-net-mdns.md @@ -0,0 +1,117 @@ +# mDNS Error Codes + +> **NOTE** +> +> This topic describes only module-specific error codes. For details about universal error codes, see [Universal Error Codes](errorcode-universal.md). + +## 2100002 Service Connection Failure + +**Error Message** + +Operation failed. Cannot connect to service. + +**Description** + +This error code is reported if a service connection failure occurs. + +**Possible Causes** + +The service is abnormal. + +**Procedure** + +Check whether system services are running properly. + +## 2100003 System Internal Error + +**Error Message** + +System internal error. + +**Description** + +This error code is reported if a system internal error occurs. + +**Possible Causes** + +1. The memory is abnormal. + +2. A null pointer is present. + +**Procedure** + +1. Check whether the memory space is sufficient. If not, clear the memory and try again. + +2. Check whether the system is normal. If not, try again later or restart the device. + +## 2204003 Repeated Registration + +**Error Message** + +Callback duplicated. + +**Description** + +The callback already exists. + +**Possible Causes** + +An mDNS service with the same name and type is repeatedly registered. + +**Procedure** + +Check whether the mDNS service to be registered already exists. + +## 2204008 Service Deletion Failure + +**Error Message** + +Service instance duplicated. + +**Description** + +The service to be removed does not exist. + +**Possible Causes** + +The service has been deleted. + +**Procedure** + +Check whether the mDNS service to be deleted exists. + +## 2204010 Message Sending Failure + +**Error Message** + +Send packet failed. + +**Description** + +Messages fail to be sent through an mDNS service. + +**Possible Causes** + +The mDNS service does not exist on the LAN. + +**Procedure** + +Check whether the target mDNS service exists on the LAN. + +## 2204006 Service Resolution Timeout + +**Error Message** + +Request timeout. + +**Description** + +mDNS services of the specified type fail to be resolved. + +**Possible Causes** + +mDNS services of the specified type do not exist on the LAN. + +**Procedure** + +Check whether mDNS services of the specified type exist on the LAN. diff --git a/en/device-dev/subsystems/Readme-EN.md b/en/device-dev/subsystems/Readme-EN.md index 48abe9e925..63dfb30426 100644 --- a/en/device-dev/subsystems/Readme-EN.md +++ b/en/device-dev/subsystems/Readme-EN.md @@ -90,14 +90,13 @@ - [HiTraceChain Development](subsys-dfx-hitracechain.md) - [HiTraceMeter Development](subsys-dfx-hitracemeter.md) - [HiCollie Development](subsys-dfx-hicollie.md) - - HiSysEvent Development + - HiSysEvent - [HiSysEvent Overview](subsys-dfx-hisysevent-overview.md) - [HiSysEvent Logging Configuration](subsys-dfx-hisysevent-logging-config.md) - [HiSysEvent Logging](subsys-dfx-hisysevent-logging.md) - [HiSysEvent Listening](subsys-dfx-hisysevent-listening.md) - [HiSysEvent Query](subsys-dfx-hisysevent-query.md) - [HiSysEvent Tool Usage](subsys-dfx-hisysevent-tool.md) - - [HiDumper Development](subsys-dfx-hidumper.md) - [HiChecker Development](subsys-dfx-hichecker.md) - [FaultLogger Development](subsys-dfx-faultlogger.md) - [Hiview Development](subsys-dfx-hiview.md) @@ -105,6 +104,7 @@ - [bytrace](subsys-toolchain-bytrace-guide.md) - [hdc](subsys-toolchain-hdc-guide.md) - [hiperf](subsys-toolchain-hiperf.md) + - [HiDumper](subsys-dfx-hidumper.md) - Power Management - Display Management - [System Brightness Customization](subsys-power-brightness-customization.md) diff --git a/en/device-dev/subsystems/figures/nnrt_arch_diagram.png b/en/device-dev/subsystems/figures/nnrt_arch_diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..8a4a218f519c5707fbb2d5724b6c1a731d76f911 GIT binary patch literal 46388 zcmd?R2Ut^Gw=Rl)AE+Q!6a^_Zs(@0Zi-?HyE?q=gAVDcXN(iEW4N&P|=p8~&D4~cb zNRyI;k^oWZgn+aJ2nlD!@8A3U|8w`h&;HN8=ehSjcRi01!di39Ip&ySyziJ}%$Fuc zy4;+6oNR1t+D|(@c;dJ;ao_{b%#V&$nwW%`@a5B2 zR&Tgyv*&N|;=aEWK4J7=-<3c0Eh=e(A^W)A-8-gp=(Nel)283B_doA{bvuUpl>8kN zV?vwF+v+{oWI8Q{-wkd5V|F>rDW!kO2J^+ zqGY-G6*oG7&avIV4_+RucI`2!aqBa1cFtbF6~`-au$ja^5VDoBss60C_5GO}ol-~p z+uhp>g_*s-ezf;RuyY+mvI*Y??mNZHn;sFdKR!L39J3E-GrYvy%1cYnmIh6O3vbVe5j~3F&?o70H^n^4ni1@X!^FGlYIZ7k? z_DJ>359an=>pVBbEuKFx{lV|swVq@dT2w;g^n3l@fDwl|b;*2R1eD-epc^OX_Vw-g zNfQ^xpqW#CANL)2(yy4;@pG;(-QDfm2T$g&Xw4MbWJo{1xrDa^B;(~t(X`3tkmSVv zRwQSoJZZGbh2mG}fPv1&sxDuJ?QE<@l@$hkQ>WR>xpwpT+!61~4WKmBCMVwxRf2wf zZ*ybrZcn~7YYyI&o$8EJ0#s}*>J0xR!hcB5ljc%@-N#n_cRB$Mi9@IatO272olpSu z!IkHxc%|7vIpu;*LN5D6h`b_I=7p5*Lt8C zxp5i3&Iv!=B2qvx7Ugh%;3U762s79X3vo+@o<}rcou6E9V#B`87eYuYoVw5H;+jqy& zlDC4F8|Ip_^J|e4jRC~_Fo+;KBu;JZg}|)XM{LE_M#gA!NTA(CgKV=(Xqsd?e<6{h zUxU8HO?_Q@2-+=PILb(0@MjBOGR1PT{d}2b#TL$e#lC(Z#Nw{=SBJm}%hTVBlHwvR z;4g4;Tu!^)u7hP?pf})Fq7feeg(+s8yF}MfW=~ zi4aU5wW5_7Or)7_P4AbCbmT1KNn!s(@~lQ^J>@{VEWUdUi!Kgr``rb=rhs*UH7h3P zJ$jXB9V3W8{R*VE>$JC%Op&}{%AI$gwgTTH#yV9!h@_}CCQ6-Ab1m_k`!<=oMjdrI zN(>}#5CL6o)+Kv}SU@80nxdW@)!cnVgflirz)tI8pYJNfty76UA#r!T+}Sa_PN9Rb z=7tZpr-b%AyaI}&(m^rBigx#=mQ#%m0F#D01=yKz*~S?k>e84iMP9sV2m3=IG;FGHvzTd_f`J8cbRk+DZYJX^@-Uz!=f=>K&1T~oF)W1%; zS$KPBlPf|?b*b_httf%3(ZAGgR0VfBX%G6TN$__630F5py}%hIMo2~)rRlC`_7cT;BW}-jHW{2OI zG37Vf3D9O&3ImPkDRl0RtASJ{UZE|YzP~A^85snuo62SdSuxPw^S)e@g?>1*h8w^8 zslf7Ae%fO#&Z*tD2fs~ouF&|`{(dE35u)Hza?La6*i4!M$C?#u{zTSm_zL}A%=6N| z%kUJQ+o;7CEPAY^q)^1oJ|$9~nh|Syzn%j; z_UDtpf5OAE#R}|fH(UXCe?x7s;D3b;J`(_I>cMh&D`x?ThwnrHAmW(Uj%$-a82d4n z4o}?tuY(ETem1uM5SxhpQ#Wq$G(eL-{@#>23!a#G&B)6aXq{9SgE{WIeEG77rY5Nu zp*q5I`gEERLM6zBjZLAL8EN$rU$FX#Z1AmHsrfgm0hQjuHuo+H_-sa$z5*~$_>+?8 zYEk@@IijWd=+Gg(44`I zeC2+ort^}E?Ya3F)^JR`cDJ&x32|Q~r!C!PEoTdLpBE0aX6)dLw6^Zz64&YH?mWtw>14*jGJWU&~8Um(^YWKY?Ft;8F z-5HykeJPqLt3(QpPTj+gOb#sOZ;D-gW1HEXBYUbvt(~8RVTE4+nz<+zX~B8>;aK&| zrlRl|td5lWw39h#|9C92z+u@4cu>K0v1axoiB`q9D)G7-M;^$SWN9&*7U0oLbPa<_ zF01jLirzm9y@if|7 z*DIho2f0n|RxC+*SsM2E$7JeG9GQb8`)%wp4+x?s4hV%!15j7ti+mggX$nJXle?j+ z@-STRt(mTeV-oFLGA$1a%}I%Uk6oENWOi!9POzYTt6-t6aly=?WoxMsiggUjLxJR2 z9_ks7qgWoFzqe=mqIUE-cY2)h2XDHiR(9Vv479qgt$204P4vS9!d`jq*|6crNgi?o zafT<)qp3jEWosKvu6H_0WDC8@W@cxRrdy{V@zJx!P!)3oso#!Tw$Mt*lyrGJT+A_O znc?4K6<*u3Oi#PGBjiUP{QfbqCvU<3>PX|XGZSEmHf2`M$R+W6Zm)?YI9mjaH z-Xm+tTXP7i*dbc`?7&z`6f@!WHg?=e_B9=1!jE$?ObV;yQidQftPCHoeA!{-g z9TtL=*D`ZVOqm*JZ;=t`REPcWs}OrrTQ@RV<#d`A*_4EGRSf$yg=SGUoZ|1H z%|lfpm3f`~W0mp}N(1uI!DKQectXDGewpNNBVHW zBIL_tQJoM08@|Qy&?zTxl5txc91&bj;a2>xjMh>3BH^|4#}wEp+vY8`hU$Q;xB;^N zbx&;LeTf)A*4a!>{&t3s6})WaeIU;+jv(!A9%yHjc)xW}$n}@Zf_Rx15^g$$DUsw}o>29DIBW^98^ss2!!i+l0P%Iu{Eg)?iM|`PGE;`Bn;`efMlZ%Pqw+`p^ zlNlj|fO)GM>?)k4xaIgy$znvGRs>DVPnA-eODkFw`xt+}uUHJEe>bMG^r;_y=>+Qh zjE{Y@tgN{4`fMLK(~130K1)Y$U1ZI>&%?irZE`FV0Yh zl~L_^owk7qkz9Lo>fPfbPBOm)EfH>g=t_nG^=W~rof+pY?rJ02l;R~NwL`eVly0=L zQIr+$e|1XITN9h+3=HKjRuJ$a?2vICn}o&7Mcl7?ivleue%8#+9P~?7%o3bkX-B-J zP_~zam8EHyivfEuGePQn5N&jY4S9Y5M$OpA7)A{i6Yj#(+kST zw7O5HFPXPcB!CxXm0tjyrpnE_%7tMy#@+iR-#xw_dgk3)&0S6AB}Z78e`VKmwrKBR zw+O3yQ;(&_Dev3?V5nlTRIxC(c}gC^C3SLkuJG91^7=&<<*{>UbCNwwoGe1Ojf3Bg z;Z9&HPTjp1RNG&>!s9K#=nVA{V<}19aTYoJ0s2|bfypgGzXj=80;6Ns;e3NT)3E;( z{)pLEEG2yChiUC3Ubxd63AmyL(2L?EytpW0-moEK7LX)}%>nDBp+0;y^7?Y} zftrA}Aa_ClXhPzd9lE;!-58Y#%bt+N{~QXINANk0Tm{z%(u7R-*f>yNObkWR!>oQb zDg70C!by-~+*i2ik=fM@$K>AJC&20>|L;C#@fmU6;raEak2BX411>jMB7LM7jnL^bDeG|L@&JialMOJ|~2_Mf7uolKkSt8*iE3Q)%< zINVBJ)_M#EqNCn(Wn0+Y`O(vBT}YfMEqG5))Q;3}b{(!hMG&iOoX+v1_;NXAyxX88EeaMO_&sAYq zTReLl9whHnSB_8;i+fJ-YJGLioUKS9Y<2uUv7VawIpVdj!r^CLdx!Ls9fN( zz4^U+00?=-G(FDtu|wN~MY-_OXKYEgQ^+rk zEpIEBjAi*Ewm$)FyK`Q2yY-p_Dj=qb!9rbZ2Z6=O`pNcBqjgYVp1{H~ zY@Yx!@FMA+doMv~p`_G~_PQ?j_xCJNWOgTk!}=x4A3t=NCdIm0m^MCg0Lv7 zbz>#v9;dqySnhQAhoK*=PJrG`yBa)*(eoa}?>4UIcF2#9^Jl07v-YBJhu8M9=D4pF z4D35x{wssEc#4oGxD}ON8WJy8cuP#K9Rh^#*b7*>4ChPA)FPLL)@eHMa0HiY2EoE?>YWa zKBt_;>`cg)jLCh*t>tobZ%lE6bv1FmQR)+9y(>dUm;4`w>?*35_~7hoZ( z>Cr;raxu#F!FW~ZkPjKS)$!^qx9_oK9qtVRKRMO?!V8SCJF;0@tsz?yp-5y2IC zX5nU*jZYJ#5c?%igy*XGneClYARhe6{Cr!JDP&-8 zt0sNOK8V6Sd5=nT@sFN6QtHe3z6DPl+Ok-Mx zrQkk&{QciIud>k9d7M}s=xVV@!v2DBC6(dJ7`}zd z&5vrsd+rDuk_$5TW|Cd|+Y2l))}VQU!V>{2F9Tx1HhyGh^B%VJT<~%sW2&QcqM|b3 zRl#Gj8ObTipDr6O`?|Yev-DirFj!k;{P6(uq&gIl+XuX$+{xV$8nqP5w_ zH&D{-kF*LuX!MS+)`c{?lk2pITfMk0S0J8m&TkxhlV@Z&*{L!#N0zyo@>HY_7J}J} zs71EfU9z0j+*^2pfk#BRS`FlI;P8T$CZpBQ#vdP?ij5&gB_VASiOaOPZ*rPmIf%0A8~3(6ez8r(%t9^dmPI)Sy8Lzu{?s)R*3#&Ddv`S`gE&$t!32KexyX z|9;=C$P>^P9+CMR+oy>io(zejHJNQyXeR^@=K}f`DkT5@EtvYqmlnRmfjmXUC)sZ= zH%R{y;PnuDYoblzd{C=qSOK;$IW514wgVr`Taag9Wm=|V#JShyGiL**Q1((zWYd)6 z8~w>n5?s6TNR>$89I)lVpK}qMk!J`Q_fs8WF0o5UR}NL9DrVuB(I{1d6X$~*(BAbl zWAZ@t7m9X37=Z(6ogFv)W4~m>0-+QfggPp3KVzwh*RVpWOBuW3Ys-7nCMnwBn&JF_ zS7_0D<`UQ`GGUREuJzQjU&DniVgBo0?~{gF2POEx%zjA$AsXKRbI6bTXb7*gW`XWIkV?Q%69AlQ44tBm0t*Iz4AP~xY4l5Hre}~BY8gEYV|M}@G9%Qza zceOv!xE7E}`zhH!edMrfJWXOx25J{Aymaa2Q?pI##Pn)^QfV(=VL&|v+qg0AM4aC# zEf=fvPBf=$O*tU5{3&mXuh>SHo}H#<+g0Rl+WSpODK-t(LNZ@OIXoFV1r@6Qv50{! zX}X1}6iAd7Sd!R-2+?WQ#IgX-ZODhc5s@0@7TeeYEO`VT%3~&8W_Dj>x%0q>Lr2v; z;!5q%v2opnCcS&V1;lIb*_c%X2q+TFIkBt2LT)B|tk7t9Y0!H(ZpZ0;{8ZFo6hkl0 zsFJbh`z?|;IZ`Z^%aq6L;o`P?CYphb%5%^f24PJ?iyHsS{{#B}96G#B-!>ZAEzt zQ)Fc zm?=`4|CNC10DpDZ?hL%)8x>fE>oT1$gB{q#e+_}FIXnDIFR|uc2AKO_gOQD;L2FAm zadbyCSz~)%6UrBJbh5xQ5lV6~UNN1i|22=cgVff&V^@VE1zKb2%X8`yD=6zdPkMe&CnQ|YR*#9E zpr(DLZb^K_GJ_YpHnk?x<(wqBPFbGRuK)+W&cY}ROz=rc|M^Bm15ytuJp3xyVcS!4 zQSna04AnII2a5k3Y-7md2kImED1V^h1HNWQg9kKl9jBq8r|h?Vj$0r_tR?&K zpM$BzLnCMix5d5WMa34e;JrWdLmU=(&mCY?wbFW1oC^;lS789q3QuFv2aR&{+lc5& zBQS4QhsWFIYTW5}MTWvCB_6!1Z%GKU>v$-8yGTze9g9SqT60vZJyVOp1z zs}z6Wl()27z}xsO?ciFH2q|f+!>W@O_}mMfBNIQ1sFgUy^iTON90Kmqo4sV$I&J4f zjKZU@U4?|lMvYTbQH78qnn z^oB|=H5c+n@9@3@f)DA9`DKmuvW2Bx1#Eo+(f<3a19l*T7l^s5QBL>Tr3M~RpDwwjHt4>+P%@>De-TP+C8Xc#&}=7V$36Z(9JcX&a^=oC`} z0E0I+S=j{r(|U2lu$2~ux8^IpyUB|XKtT4~XEKi;qkzv!C6;-6_)9Z2K(Y)Xb(rI^yVIk0lxP7V^}trE`GTIP;W<#G_ziwl zrYU`^Hd_?uarF>u7Fn4JdW~PL#d1tU94>y}hF@V=w*Bs^#k1K@J>`}AbmG1Vfa|lV z$vjsmm`-W*?Y>t(ANVY8>}o~u0Wr~OzGCYed5l$N$ck0Ts(0k+DM3WNR_du2o(QIs zh(({$L{tG~0N956O$e8vHH&$$rS2?7_Q>0a3+ftsy>d(B;zo;&tsOX!N-)?N9CvpC zwF24a-TkbGACGeGTD3GK8@N6u7R~??&SJ9mE-o=PTBTzH(ydiEU2(Iq zpPRLy6W_L`Yp~wOveOip95cETavdC+Vz9So zsQW-q7q&Of%Jl%-jnG`&aLVtVKE^iMkxJqTF}`%|wzN+Y6V-*kM2Jp@daZN-hkZHG zdVPzQKLv6sc5^r*AVjh2tC%`5K9}f;y)xhHCsWyjZ$U1nc>yZD9rWP9Gzc$p#+r@S+m4i-G)@MMXTPIlsY=bPW-7OuI6qN8CKQ4`QSX5OP$PReiwM28NO5LBm|*=>feX+$>c@Kx*Ixr z5Ky3p%V#SSJqg!4`Qw}a2?@IOI|Kj(KUG-4Puk-UVW7jn^&gTjmPWI#e}!59e&GL| z&HX22`vZ#@=6JsDTk^3=C9c&e&> z*I%2Q3P3hc0kCC0d4}zVVM$#!zPAE?Ed-279jn&U_F+XS!U;JK@ha;-_QDhe&|}Y8 zEU_q<*B0rJe07TC;Hkl6TK|p8O4PYt^dm5(dJDLLOsA~!;=t_0G6#2q3)`%i^$ki= z{O(BQd#TM6tSwA@56}{DonsMq(J=MjyE*?_iWBSce|c9jRuQ`0Pwp*IAm9DX`ioF} zO1;;RY4Y;Q%9G)oV&dZ0wzs$4md6_kDk}&47ja#HEQ|CurE6_#6rCX%RlQA&KAFEZ zpHO%~JMe>Y@&rNN(_$6JV$eT}CnK%?ZJ{Xb(O)b3uAFv@mQq^nVD+|0Doo7ArJ$*G ze2JRg@iz$km#_fYvu05BK&=9uGVt#+*yNF@?6r0iTW)y~kW^8w#|u{U61e`AWU${4 z{GVmixRW)LPbS6#=y%pPt=F5+7agQ%QgkWCtXJcKP0}098-vk8DY-kFRX?;PmEF+K8A1=nnH=PHbWrhCOvm7OC8itzI%${-! z4dGLQ_L>7JwMDi7AFiT1wjBh;#%ke0Zd8N>C^2UwersdpDu4!yXdD0z;5Mmz3}cQJ z78v*c0e!lyn&VP; zcK!WuRnPvuFRC*e&IQ;oM4x$l=GCK`k6M-FRZH?WhhEE!Qmb%BOHuh9m;f#-i;MG( zI?_*GC#CC-t5|eYx_X4gm|LH!BR1I4#?c-K(8wKPO4k|#8$A(R;G7w@Rs~xco>5uV zJmQPh9jvdEEs%_l?+ZJ+=A*BY)**!z&_wp=q0ZF-%w)ISer$p)dxyLsLqZxOW)lsD zb6cohqZ+=%{8dP*X~c}7(r<*J0qD%8?fR@#FKHP*pwY5i(xX&AZ=@SjTSr94C@bzA z3`tMlp)XgxZoWecfiCida3$?H%lrH~Eu|DEy^BACPJ%I0-BSP*uxx0`$LV1YxL3;c zfZ*}w6ovMuihlv}=I8fomeX zRkc$i5MduSxJ`XLx>`S1u1cx@u5mh2fRFZV$p%QCll9DuOccM;+x4(jcW@(Zgx$B; zqp@`&2s3dcaJN>P{U)TT@#^x{pH9Y*RDyK#5k^JN_iG1RX2*AMp4;ys>Jk`Yg+!|$ zW-5mIB~tHajjV7?Q9JVya zQk()7HDUq|cO(y*p83_yUqjjD!OH)wQ74J-pQSj_$HDmQ?EDENp5MUuPD1~TayQTGV z|9dN>9dS-2Ng{qiC=+IbJ{s`BF>}2IF$>^C@5*y82`kP#LmqGsBC0uc2rZU1cnzyk zl0y*#R?r`b4hTU>o}ufsv`3xTRiS4HUt*AU?!uGCk&LAL7Orxhn+vckMj6GoLa$G5 zjxq-28%tTa2uKH~0f3J0gF1Df`eYPrtq1I1g2@%Yj69M@58J z9@A>);h4XvIscnI){ug+RLQ%<GS(7=5gT8aa6&Y*}G@p;KtA#k-ew92f(LwYBj} zEb9ylRX-UO*VgtTUEd4czD&$y4D+KEjVsNMUAQc1O$c*c8g!OfF}=>NYg-6;W?pEk zS<$>>?BhLiE(mvRG8e}q;gNo7M}6&AJvTKv>LpPo^^E_gW5htM#Q9+*_OsIStE3A> zc7LG4to3{F-9sCuKjOJ;CO>SaQRw-^m7FYtx=PRHlD-5fd>ChxLSp`ns*>ch9qh?r zed$VdjLOYGdg~uex@7R*_j?d&P~x0hIrZB(L%uo~lt#sX+}Kt7oGj5qNXUw55GUS9 zBkV1h$Bz5~h!{dsy7Qp=&R13#YY4 zjFLcV#a1a?2KK3D?AN6q9`gF74r)~u+NG<9cx8KF9IhsFPw?4f{(W~24j?T{_T}EV zv}f$9N1jsI}My1+tV)~f8DGd*>j<4hh*2DGkUaUk-_ zct;ZAdJ}7*9&-Xz@mN-xa-5nnkcusnUd&T%IyRTvHI& z%3wz}HJj%~k%&df+pjY5PDT8WHmcB?K|@n+pR|t>2$s_K&5#mE^Y#hk(-OqYRu7L= z{N3>i?gG$5^;b#A+Y6SlUXZ3QN3a#^u8oXD(?p7ycotIJlA!_M>%Vfy&htE|cWUCo z=yc)N8h{}5O>It;}qGv6518aKz1`5}ir?QAC7nW>{umbgoH^mKu$<{5EN=ER*&pK)WD;T)E-5 zvVp|>rsWCm$}GE4|MWCIZEJq@z*sRP>|$fH-jCNexl!8r3pnwwgJ4%qqw1Nk7|IgX z7}YbR(`vWZ0m0t&x64OsYrXBxs`kkAAbALRZq*nYt`MW~`fqVFSSfqrYP(w}-vL>ToG5|(ff-f+ zmSZrkPxBMU?Zy}ib&&SNJZVTO+BRuF53qm4y8t>VUY2B{!il#a>hkW|T4BJ%Q6^@k z349x1o9Un_(_ib0Wy*@r2Q*AYq|RKKP=bWo3{3GQz@eb+`#r$Af$<$q zwm(xOy>wdBu)=8*+awXMYGfOyw!Ku#Nugi0O{Q<^DGUf&`HAsMBm=awffXlCvV-B@ z41r%-enI^x7rC6*Z*X*EExRBULIVP%IK5un+r#~wF;yKyRhLz zIe9epmduIeW{tP&147}PVsVBx;43b3`sBuJ5(;m(w&sJ%N zi?o{V{0fPV6J@PW={r0GoPqbB7SMX(Jsx1n4s6- z(5K8E0SWFCvezwfZKQBYChr9lk5oq7G(3qynvx%53;B3aP8KZ&BwaS)|DW;S`1m_( zf}M9wP2Y9(^vHer@}(dv>*Mt7Y_N-j`zGOeg9qV(96jA~_S-&iUzn==X2(OHuAg7r z+Tg9!4A#DO(F@XYZM-MGF@|9Z`T`t6+3!y+Ylx!*B~uYCri5l z^)WzBXvS3_s^p3oCL-v#IpXiackgx+EI;+s3#v@s61%fc9%IFvwH#dzV3tmN8bT%G6q-cVYp z1TVDHage`5Ba{N7x7FSr4_0j$KYFF@@1i@4hshPJgH?`TCkVrR_3<&}yxwsjB(sNK)0 zI86vWENxOq&2xubj`^mMam^))!dhnc;(*b=Jz{$8!?zYCLNr94TtfD3EiMJgK&=#Ps zqmBRlSt+Nd?;%Hbzdt+LluZ`zExB{%G>%o+VtlHJHO2q|U>5J^Zf#A)^(feC_)gy; zW;Jk?i5PwG(9Z4-UaIOenEQt4gV8438~qm^JQL?-&Ogr7fGu6eFD?!v(*-hO>>v$a zs3FuPPr#r&6nc%;s}q$t%*9n(T{V+rM`+=iQj})xA}k*F#3oyGoqzp&tj0aP1^!hjgn}L9PfNY5S*{=xTK%ckd+6i2D*9}}<91eNP#9y= z+AhRO!EciW19Xj5aS1XrTDx%Z$3GNgQle9(RZ2enhe-`xlh30&Q`e&qZqoJN_Y>!3 z09l9kHppE4JCFE(_0aV{vn~H;=o!^|gIH`X3Iv(6ME<`V%>U2wz5YW8Tdnlt$K%;1 z=fc!)2-S4$Bg&uuh7>BA)?Nhx7OHQ;r8555Qd8QL3Q)E5zDw>ic16pq9# z>9l`~@B@Eh`_6I>tGBe5Sik&}jfnq7br9kocH#hZ<`nk=>fM5BkkOi zWSk(wWj0gXEO!vTh|SXagWp~Og!}q$H~k(Tn+bgI7z;}Q*Mn$QQ7zxQh0Zv*$^`m& z9?W?g$su;2$K3eoDkl;xHTm*Hq^gx61SQOJqt{r~NRveW zr%0}vV1@^2scHRNfhV>Ant~<+6^+%dcTpA30B(J5Q^z$$$tNRK6CTz8+` z0pMnc_8W(9AC&!if#SydneM*hibQX@8lW~Zt(i(FU4j(|#q7*!?s+CBFI>Z-Sr{Iw zY%B5`rr@qO|0$>5#WfV&sw#d0@#~@QwY<%SfW_y7@Ca#@r+R_ah1(1tp+p@~VJ6pY zsVTs#Q8SRdA4ZI42D-{r-{Jiw;*7R7uVWecGxL{*;bwU=^FJ@9pR@rd8{G`}IY)h$ zl>0iWlB-!PtuAPN7Ht4gRFaC6-|Qx@O`?m;@LR4osx+}6H2_5 z2{N|dfI^8SzgCM*10udLfLwjj#*ogSk&-b3J=67`nn3mLuq&_j8lc5vvYwOv>#8bN ztqh6}*r~QpKk3RfR(bKX;`2c-UEagXpUlZlO;4(%%oRHwd&Zzduwkhcvgv$Bl51N8 zyJvFl+G2zrd6>G?FqZ*U2Iia81c+6fL{lkeZqARAt+Uajun_t^@&I!iz)wrp*0I5x zJDfxxmC44h*e`EG49OROY`SgZhS%BtD@p<@M+8(-)TyJnOQYodTLAs4tGL)qlgpO% zUm6{RF7LM@GH~X`V_c)&u?%U<(u18%vNbjE4t<7I5zeywly!q5wZ?kQ*%X)VuzgQv zx)Z4vjC=F~ml&Ofyfoc&kDre{?i8T-#f1EbM3O(qh0=VJrVmJ6)OxK`Fr*A1TY+Ql1Hcgxp35zC2pu@aAzs9=7dY+$61=%+N#!$B{-#2{LbvUG z-d(m_i#3wdjy{5_@T44I7p|KOE)4<*WwUtuHmOGB{yaa&s9W<-mausD1^;DQkP@ z3^+50etqIv;6_+0pyErU(B{*dbxZGb1*>;g)sz7 z*a}=9-X!|6YPxBulXYz28@@nKwCUEiqHd|7cNV9$h2AbtYpu^eb0RH1+&N&kp#|7Q z)sRmjJCy@U*I4F;^3t)u;t1mTV#HV2nT4Dm!2Hz-ji(MA$TnI7G+2r5Og0({@CEpo z5Aozc(NQ_D->*C?QpWtv4#f4w*AknIS_7o2H&B{rq)K@RV0JU;<5}sFUC}JUUU6)C zcUC+IrkWS8IY^!7mqEOULf~`}?+KL_ncE??Xb_l1X=70+0J3$XFNnlj<@YhE4-cjQ{?EH`Ca=k4Yc}unV z6>*CsQKGhkIvd#Q-vrQ!`Zh0Ha;yqO#S|;!4pLSL3x>gV77AypIt6P)vm~5ER*pM7 z0eO{v}3?hK%3}J;y`J6W4E+u z{7AMcgh8j(iH0sKAWx2ltTd0bl$);#DS=;4I*r)-8QKJGDBTgI1N4IQeQW;ubBB+M zXBMV+S^QM%-Mmk<^tTNa->2H6ULr-naUrugucfP36b5TA>c+~)Y3vj^7~#A`?(mvV zb;Q)n42I~;q^bo~Hvr|Ha>0}rv)B+9T#@PQ9&=@H>1v{uYXd+DWLv^dG1P&$$QGs* zYa5F;ghvlOrW>pTI6M>#nttb+siiXe?7&gJ$k&dUZe&_;Yb#>hAVJGrDeI1+^c<5{o!8htwYOjm~eWkTkox0N-1n4_O2T3pMpB^Qjn+G&giFGOntejS#1RSO?LRe2RSn%5f zoMH`vuId2PLr6FMy15RV&@eieI^easSX!Y7XRc@VIKJL_GvXe;lj7Kbfu~=GfX8{M(tdp zZuT2T{T!D9irM$+Z<4av1kD}HQiL(=cpfd1YF7X!Z)S|_a_VmeiKzIPj^@(zOK7*> zwj3J>W3W!n$n+vHH!I+%3S*d}+ucn59b)-R{V~TCZU$l)_yRt~I*p*;rS=>{07nX8 zAbV%e-OgMIhLZy*8gT#R5=NO{hk^JL%}tznA8@Wia{#9NcKQJ9XK`W1-E*P8+Fni{c+}yr_NU^zT@y*kxJ#OEPDG#c zz4M?`Akct#S=0Vx*U^|;YZtD)YdUCrNoKhz|I&#}7}X}nt_}j-1@_PQ31GmlzMSsz zvPo_#x_im^>&dQo4$PbB=zAA}o@U;0WJ^dla#(w)@NV~*0Z=yf;F(d6fJW$(3qcpW zlP?lhx{fk@vEZsNr(aILw11eawqS6{SmR{Z$s<1Ez$o?u4v1`&aq!Z6QNObRU0gyK z<8z5pL4)p{myQ3FU4AdR{c?MKjtINh6<_ihINB!uPDX8{kkc1hCV3{y%{QQ`K_^kg#LewkuubaJohbmV7bD8IpXSK(B{7Xw@vzfuFqv@i+{lcSDlq>ft zh2J#^A3`VsZBhXTR#Ty=ThTMER}6zi_MIH|BuukAu!2?8B(oh`we9J6O4VWDX*yu? zGgB12lIjwMT%at+0pnGKS=0f5k4U?{_Nh}^7e4Zy_u9*8_WSc2&WKnF-~`;ALSk7K z;UT(0r&&obcs{$D)-=C@j*2!E!Y{0l|2V2pMQRN4UFjeDdKKi(4&42J`l0+^JSz{yZ; zOo4$p^HDWZ#J97KAru84@%&6pYlnbD#ub*JiCz`WCjgr)6XNqV<(kV0!!-G^`?eHg z2AGq)VT%jVhG*))D_D9;Zzx|SKm{=Vh@^E|>)wR4_J-{c37%-a0;DS=dfuE-pcNB)DeNStsQbjbACe0>CG0bdo$dY^2}la zz+lN+^SN0@umrzBp007JpTPtj>L?!@G?$Te(1g4qj z`hr=$u(AQ1{b9Nss^Cz#rUo2xHEDJ?Zft9H>SUwQXc(O$x45B#^IA@I&k(2C?y}(f zUP}}r8nay2$^btoL_j6T{>Uspi9qQ*#xCGCE(LGQn?h7ZP+lX_wb+n_a?G*>ZF_y# z&gXKh%3@KqC!j8MpMfKoQme7hiO}`Fmq30cFcBk%RNMzN7J*~QZX=TXfO{^t(3e$x z#M#3AeOWvLCVZ*CUp9XCehq2A$leX257!38V(nI6SWlkMx?JM!M>I*S!N>o-(Ct~) zNjs$H^UQ67%bJ(K3U)B<3^l#lb|zrDQhKB@S4w?&<3&}d>3!3YZZ_Om(>g`X>KCxK z!td3(P^4@qP@%`0-QJ7dgr>B#nOoA2U%dTr6Py9bA5?l@qIYR0%3MLuqQDzcddD%G=)=1Q z911o{i}D~94O=L#a5qCXC^_A^Q-wYdOD}D@O1h8gX4)hspLVXT6S%_Y_^YTz=wF= zGt>qUxhU#s%e8(B0AYZ+#bI_UNx8JfNy!rDoRO!Q%$E58-n<_rsO+_RqTI#~mN`^C zL2(O4k^{2Cc<>hn={Mj`|AV&ojB08N+eJ|~7TDNm3IcYT6e&Tvs1&7_(2EU(K$ z8(;%e1O%iDgg^ixg&qY3r9%iMp@>K)AT5+o&Rp#Mm2vO+&iQli`r#OAAZsOS&H27h zdo`KnjYjzIW@#lWQJo>W@|@tk2%$e-o~ZILi_@N`>0OX|F^d&DAmIBttcb+>g93`b{r;9*Go~$%GOgj+YBY?+ zOPMWQ3wK?inqqmv+|iM7={*Hg^-xvWE=_UrYVMf;!Ds{bTtk(%{h~U(&Gs3m-wPgo zVNb@4yw=xei8r1Xrrgl6U!&gHc-7-7l0vh%frsJL-|~)t4}-ju)VH@jj_39+wVR*(`{wJNqw$m%WG7BonKwf6kg^iEBo+aLzP zQ6*F06vr_9V~#O18-H>{t?!iQ=RJ<{DP}g>;mut&ji=~7bY)6Q&#>I8Jq2YPWG1Wr zBIdc;>cFQ?!sL7sLARN!CUQBrN733cNG_H6xBs$|36kVKSQ$@w+c{&1pTegP42S3^ z&XrHu-kRVj;>l{tu(^!4OIDzS3>wb+SqLJF)n@#fafr8$rRkbWQ++clv)lfYVMV<$ z1o0Hos*(XFV%$BQOCV%R!X$dlci z?zv13GAhwZVN@tv9PYY8zefze(cC%A5pcNBucB0|a}97i1NP_2?-hDGEB4Pm==Am- z81Uc2V$$46RNWX&{UPMm`8-b&?I)9UgtxUI?r6m6xnGw!H%@m+>{a^0llo`stk#GI zjDqsJTlDgb-PcO>?Mmt1i1fNFy{Y=yE?p^kP=7n-}nv}^9xd?lGNc<7xZMk`hjNi@XG{d{iqdYlqb@mMvWGlM4U zd-)?xbNLZJJo2>N`R1cm>q?AD=kLom^o9Rc zdP9lGtD@iFeSle11!01(+&L&SnoO&unY-4=foBG5%gN?w-s&9FteBL?mUz*u)yNQu z>8F;&wEI4nKXMkw87Tc23eFfUh*PoCnIXsz?#)346hAlf{Q`Udl2=cq{yno2r@xlN zX$2Yy*!5Lwi@uLx*tliA*d&6*omY~P10j0hvc4nvoU?ifqeC8*@fN&6!Li_mX88NQ zO?$D^2aGcFjhRt`*8Zghp2obdDz`3M3dXC?zIU-w`qBF>ik;+J?N^mVwf7S4O>U!; zM1nb{?tYI5&RU%GcrzXw-1?UbN#s<|kJ@pvs}64w*lX{Ye~Dnk+qa7)I@=HOpnKnJ zGalSxTJT;EZdck+{wO6P6I6^Kfg+zpFT8o6w&OB+yHm|@g>O+vT|#$0gjHtl*L7NU zui>9xdgN)pJQVl}9wafZUG)V;bJUK%X6t+pr`D+Nncu^b$XEuxDQ?P(S3(PHrAWZ={+W8cJ&z>Y$`nO=4&@_kDy)^WJbagt@Lar&T)O0+mDbm_iax^MDxY;~ z21$GVAy#*%Q~vqJ5<;=x{;M;p2DQlxuRPJEXM(=u2kwZ zB8lU@YF)0hPH&vu9pPzXrd=^V{oIbXZ_5CRp$ni7+h*g60XZcnsy4Lh@sDeUEZ zOro=5zT{$^vtlsaS+PikDkveIvRdsdv`%aWFzDzULACq{UO(wlV+{#{bXgV>%7RxA zA@LKWHC^GrPiXdUdQwVTxK}@e#Y+oI#&lrKhf;)~7Xm}?Ibq{BIN-H`4z$+P{N;aq z6f7_q0Fmz=|J!6zPFiH&itL&LYCUIteImW)4D?c?Fg|(2egC1L2jq`8IRUw!aq$}r zXAJ;3#l`RES^=8kq^{!a?F~Hc(5vywIqLx4c1a7K7A@IM_mRR#3=dkLs(Jq49{%Zu_ z!!qI)MX&5CSXgu*!r<5QkTjOlxe$WCu{!SoFi@wW>cuAS)W}qzUl@9~0Jf(Cecm;I z6Zpr6fW890n`il%*Q2N&A)xSdfYL*kplW!|Bb=Gi55=W|6w`aWw$SBXg+pef6I~LI z*b1q5*9W_0+PxUXhMxN-0n_<;RH~k2c^5LsD?_F=O_i1aNk>`4AfxwPAfKevhJ`>f z1ZJNheG>xkVCP@xri6UAjn@ZSu_xTWwNMgZr?<*)Qg6Sbq6~-vP4gE>c3=Gc zW2kS@?4CH;r5=3>U}wuy{vo(i5{Atj1xdMMRi!hZ82zA=wIQ4WdkrnseR#vg_G07p z(tdv;QY;T>CR`0K{S!W0KGM5y&*@06LO^Z{G8Q_ug^)$0?TuI4hs91!1EGmkZD>VJ zSP9UpFksh>X_l3g4$6RuXC|o(l;6ogAjg!h0-B}LQ6P5l0B@#Q3q;s5DzZBqLH;b`Q`1Kq!Qqg3Ri^DsEf6Zq-div%m;y;+IAdGI z?!)hG5(v%o0}`g`;@h7M&%EU;C;bLdwjk`axhV*QDkiZ@mVY)F9VWhYPkM_;`?>Jl ziN^gn|3j9e*nlq?QRSzce_u&}r8{6V_%z521X;4+3XMd~j65?zq-%-U^$8Gu`O2;S zmd0Cloo-7eaTw(ax&lRhCDCOgOD}*e1eq4+`G4YacTv(WHqdx6{w6OixQVgVeY(2G z2c)V7Uau29VR|&19tco7WD?X{?jkrHT6dCYf;%|t+B)eSoY(_1Y__y@4}^~r?AXZ5 zwqt@Sfh7v?Ahtj*+Y0Z>&$pN$hGodCdAT=jQRs+%w#$>oQ95y$Kz1slTNknS$k{h{ zQA)KsmH{A0VBfIMANIzbxoE0?iuX18lfU+!cZdNI zw9(qg5%U}M@G>#WlqOb_Y^~_hFm>L*N#4Vz6)Qb9$nfRKPKLjhcIF4fNzo5p^4}$E z*Y48NmHZGD4FmGq;L9wF-P!0RQBfDouIp#Ug;#+r+==#dA-;$CFcZs?yq^Y3HzZ8Y zylY_YQ=^*-9EtWB0UNG>IO|RK^!sIW(5xnbYssDZYV9$B@XZB+5D#^8dzG{b zqD{5tzeVV3Nd8=sGTrm;21Uz9!-PPq1qgY+3*N)eCYv;#s{WzL7h2s;7eTpR2}aL; z@4ZCHJx;0i=E$rv$_DTd;n@7`ygz64%#6-~6zDX%I#5p#q$+Fl_8&gw%rxGV59{(G zW1LJZ`zem%mssA8x2Di)sd|4?0ft_qJysFM-}9%Yd}KT9gS((G4QbJlcU1q;JL-rx zF$M!mRe%2<@9zz*pa|jKpXGZm4Wh>DICz~kjX5N?^x<^TtyI4y?M|sSQ6pm;J+^Dz zEL9>ZOYE?(a|y*Zb6tZk#&h8krM~q0IbsDjR*i%NGhCt$-ZkhZ`@z4sbdR${D!)k&$3_?qd9H4$;9T;YwAb5iPSs zdLqj6}FYP^qg7t90i3j5TpmcSQdG0OCAQ=I6lb%1h4LFzUn=DnQ#=h~yksC9|HzRF>+ z5g?emD`yp<(3WPd!CiBqMV?S()7lWt|3GL5w9~jPGc$4BFVP6bQ+bft=DSJOiqP** z7!KFXPDh;ju^VrjbY&Wy?KX@If6YI4EgZ8DMm(hu_V4@O*nR(_ z*GUB7qECL|pU?5-(s;Y=-?&R~M(7r8oeked&yv1Dtl8akUbo~sC7|RDk#bXvQeTb| zW`#qo>A{I3_i?J>YxP32*htAM6&uq9NQXVf($$>|w0>^M(TguoqL<5sz!QW|mpL?a zis(U>An&-op!OOsIe#DwM!fBJt4ccplrm55<@4DoX<6sRSp9o;kYD@qM?z%xIC#2O z=mc6DEDOs>?lylL`Mgeo_q6E44xfl)e8omLKtdR+4aUl6Z6u23QZ|P2GHllAWvNPk zEQ5?1H$6E3a}MG9fb$rxy>z8h!fnIv>rWi@Ffx`<05V?vsd~;<$%aU8*2HYWaaoR` z8)Sqa(L>hC$x|>uMXvbqr70@Dfc~J2&PFpcz18eFW|X&o?Hg;_KjFJy;q|U@)s3GP z0jx)5PlXqlCvh68bm9Pe3|xaNPxi7$Xckx$!!}y~j!;1u-s12V?+*U`M%%4?BrgcG zmrKr2^mZ@ouc2ZG^^lPC@C{%=OWFaC@A&6^M{r9yr4S0(-~t~N#t;%vti^y*h9s0A zUfh~-ChF8()W(#sO`4(F`d9aQO+Rt!{2tYJRx=TTs((K3bENAivhzyfqW_4gPyzK^lR4(H2JjrWJX4yHSUSlK z1n9*nj0GnP2dY4*kj>%N(IXWygZ>c-m`A;pey&Rp4~rz1Qqp<^K-?k!@ir$VmWP+Y zc3O}m=knI7^#1cLer$;li_wzz+R9ayt9Dt`8~Kpm^Wkae&tK1J`~J^G7)yqMvGRF@ z+bQtST%|)%t!PsKaw#nh__PPLgMVb{HU~w=?(zST$5HY5`FXEGE^h9m>S`5JTU$3a zHa0zX_acQ{@8dthhc|Iug|=G-|0+Z%IOBUuwA@zxCm&9E=rC^Gx}}Fg)g~zi6p3EC zB=;ZT?j|+tSo2~VSIOX=^l^NahhF{f11a0PC6nE<<1+Pkj$WPw5f%`j))HyK4c+|< zW>VJ+?)b2|Is5gvGn0q$&SSg64%k1GA{s6Q;xD`8jJts*_X zr)*+gsawZ$c|kk9Z~L8a9#zdGWPWh9Wzn&@^+UjT;C1K+H=v?)`t^i;Ai^?U2eE+)|2um#aBlRv^`6o$OBldi0Lc^ote+7L2KA`L22Ps#o{u`4z<3g3+Z z%wzc--Cs=mc?)0E5G^nfosYs=6J>a9Lu>n8=WD9Z=;W-9)U=A`rT$Xgm2WCQdZ7c} zw6SE-c0EFDaqXfMK?vvj!$fxd`40lje5ZDOyp5)X>>#|2%qQdS$k~qKPjzkvZ;$hP zP$x8Y*8iycSNG(tRIb;d!!CjN2p3AMwbMI2Lc3JlN(J3?7+IBTA$?^lVlUIS`FWPt zwl_L7Sny)XqHB4R^zU-@euLQT7%2YhsKx)`UWM+r$W~ElkIj+}mF}A2{v8D*Nc1ua z$^YcD?$R0yrYmriwWli#S8o+@jw{omHdK@v`&q76VU&VGCXy8EKEVLmSdt?E-cv zAw2ptg|+vivxEcdM8i_6^l)Zc@}gP43Y|)n-3eS!q$RvZluyB0rIiE`0khfd+xLhT zGhypFi3(R@`ri!;JUJbo{WE^5J9wYbgV55@Pl~AVC8tCQ>*NLIs%(k^V)lPFvuA;f z?Cx_xHH&WHJt<{K2Q%?TR&zE7we8JwWq+6+P1HIQmS2dI9H&AH>9LjPR75Ig+Bym9 zKhfuq>Mz&}x#rLU!dMSRNLfo~qagB0`b<&9P)gT3Rvo@P7p_TX!3Z0+jx5B*^+Ep` zI_yuy@5Pt&O5EQ&jCI#D@cUuJ*y_PcKt^nkH^pt4@1Md~-;093=K5%DE*7^}n71Rs ztFbZO!I4c+$YS(XbGHviZ=inOX#OY$AadR1khcm6>Frj&g9grKzB9Pj)(^`eXBKh` zpUFiKxncbN7lJ#wVgg08pkInmU^9A5Y!jV|`jx-cxVU>YiEYO=Q}x)T<0qJ=f0>Xgaj5hf_MhnvKk z=DuNkb9*J#BP@XseBB41c>|wn2DDohpG9Bfa&8^J_nNc`LaKS-JOQ=?FbKx*f)slz z-$AeDFmEi%TZ`_AbAQP`^LX)aYZ+NwZ($e#8~c$D%UFoIddEI>0Yew+nUJO#YTk(* z2qr)4C~XaT5F?P@CJMttnT>Xjl=C&KIWoi<`ychFx@aeW_;o|De z7xeVCJWdd&qO8W2Rkv47J)k)c@g*XD>n*z^eiSVI52;Wp`}7+NHr@KSTSq3Hm`O&r zv)YUUv#d>ixyzfDXO;ZkWN$BPS4e2HQ=*m1yY{s3A2*Os8+yN0S;JatSLF}$G^H5| z_|wF3HTfdOGeEu`vFd!iD6-qKxZ&NTzea>}(M4KA#%OM79$O!@X6`Pw!PiD!J-!f* zL?elVJq#N>!ZG}l6ntVeFYeZp6TPRas^FfVjrX~!a|b97?C?bHWTmB7VGWV45%E9# z?hxx)U1};>7gzdao8=AWJib?p^-hRf@}}RMI^k@G=^T4ZG8HOgk9aiJ`^Lley|-_EI@>56shKit1v^YQtTzybiaj%4qzV} zn*kRm5^88N2*C02P)SdtHI*1GQ?sQX1Ct3zK1e<-xB9BL^8W zy>>n|3inlcL74cKKf!@}hJ6&}XUsuWU;cR=_Q&*e{Gov69O_5#h{v0zMlzq=;5FLF zA3)H=Qaq1?6GY#HHtnc2{vq?vrCUA9?+YYJO_8@M1q_HatoaRZ_QtOcg|$a2_u7YH zIV!nAeQ5zZ-)+bPQll=_8&iC@1I+kcfBkMmrWjPp8#?;Un3m^yU)praOf_$=28$7L z9nJ%KYq(ZCoXo>pTte3B#D*3Lh|@V+iw$Prp1H^X$Kn?&nqH(z^j3V)9)I=0E_BJ| zz)+k7^$cbDN6vv!D)JtSv9lhB6_;P*sg#KER7qJ5{UDPA0T z?kE4bpGMyo`yZtDH%=j3r+NrLLDjPz>;Q|-WLDS+1OP@AhxCMh+rU`E8iiAktPiP? z(9;eg8FrD>jGi;NTS#E0aRNBvknEbgbH`^nAi52Sq(T#foI0~KodA}n04!3B$Q}cs z&_9p1WJ*hEi-3=&Nm)S}P!F9!jsF&k(+MeTA%B-sYw{S!BZuB1yH=nSNrrpoY$dgU z;YH5-Irx677T9s6O;$4BnHoF~JNofn=BR?txE?uM`-q1#y*tlPsA^ceNT1FY@>xMc4 zvvMhsP#3@Z2EOdJme}l#KDef`IU7$_C3PUJ1He)D&C)N-J>ve)fZw}Lz#~V9e7BMG z-G9Rk?z@h-Vz=aYi;PH{K91*bXUgRGf9`h7KFch|n0>7Ff~-j3xXRr{x1LL=1M(|A zUbg|edf$|^z5Ii)9^h38(M{i|k2(_jw=%9;(ysDdiv3d6!)whH&rYm!k=yjCc+K|u zYy2GS3EJ)1xfJhi|M!9b2W`s@V>0|}&9T;+Fy~@q4-8?iUl1fW|M6yAwWwGFGLezW zz}nOjG}<*sH)(m^T38D*A}Ki+c&-ROG;Y7p$21-lHH~BgyA#ClY{tFUO&|TD;)w*X z)IukGdcS?})CDpynb9n(sTWLpL2!c)fYOsd&pMQXP>m30y9OCt1r>8zBt!G|lI`?<45AP_LN3V7bq zt0cKCuIu1JB`lhILxYP}5Y@TtCRW_9Mc!2a-7j55EN%ewz=U~`&&Q&BeXXOYeO>;# z@TcM+B3>49DfO$t*EL6?o6uWWZ^QtQtju0v^+16qB2QI~Efs`>LOMwzd{izvy{YJE z3rPxh7({IqdczZC+f~R3Kd?4TvzdSy^Y`55Hj?iDIzYcaycUBl!l(dTE!S_RXGr!Q ze_(+8eee)FGQGjLIoh^kqMZ}}<5hk+=hqx!V&p5Ez%c3dGb`Ef%h*gsPr*X6q)z6u zy~ow#Z{mSoQ9YFG86iH+%%3faH1EdxCUtEu&9j4I^BrjXKMicFfl*;dhc7AF*1DLa zoQydD0*flt2o8JJbNGMA^}=Jh#$8U{VP0FBykfzNwP}vECK9X!!#BNXvCs&Mf4&Gl zC1X3d5t_7NJX;7xhSo<2Py~vExG+-vmdg0RJz;h?RwXssh zyaz}MC*W0BX!tn6*U+}Ss7P66wxJ6g1(CRC$oE9qsW>DIx+t9`{*^x;Y6y90B;~4!G z0rE<*-4_$wFSp!Jn?8*7wfPP7PY0 zP%%0|&?PSAYivl{Rr-EH`c#Zn1TEW}jn3TZwydSjE+%G**(6g^_&EU2&MyFswZ%>1ug14u7j}}9`&^pro`<8Dn!obo)y-W3+SVTk^MQx& z1Q>2dyZ~KS-3Rc{GX{cY%bC~Pv8H}LJUa@XX2`4OH@MZ(EUUdWCo95p2Z1f)^_8Cw z_Z|PiKK>Pmk|*Me7#qM9z`1Y#-#WlhD7UcKEERJ7^1X&vUxCOlZE~0teixWchB{g% zyA)HJf$vh8Hua$G!xV>Ado({-p247x$Q3X)EW|u5m!nPAspb9mARa0E>Mxb@*dBof ziDC720QQ+C+^mX#bMpGS!n zi%s(2ptI!Dur6{nvzam0KSRMS^!_nMUc}NkOp&L0JAzI~kV&CL0qfW_*YbuLFULvV zIbZe+#4$y80X{)qU~VOBZErDYVUvthLD%=?E~mEYvQGJR8xx$8oz*BTrqQCv5F>Cx z?iFJ^w0Yohtmu6dQ-uhhS{X?YdhjpwXO?Mdp!jXS65B~%n>6=f69*Db!Ryxz4@?so z>tG#=nljw;%qF&nRuwSs{pcn>_b}lHf!C!uj>>BZ{<(Pr@MMg z11H2%u5B^KUYSi^`_+j%9_qf0wy7~y31Q#3Exy*Oin|0Np>##m=7Kgv(Uu`7Vm^TP zr1E;fEfaO#ySyAv@<3VNSqvEX=0*yV_0XdPR{U{XV$24(by?HqBOsG8CJup^oETxQ z%s*hvl@meqfcoZQToB^RMD7YOX}qEBw7GRx$?+}`+0e4Q9wT)s*0l7*R7{l{cj;iVXU zUX>vwSW#i{)?_(iX9p5+-!VE70gn<4M)!lCZDI_gjkDdHxy{w+WK1v}y}6MxE>+CH zqVg9$#u+T;zEI%1TO1kLH(xs=xCG$$_i=`5{r@;Kb%>-%e?IWv)^cA3i)4TY5`FUj zIeOxul8yoet(pSrgfz*17l*IQTIX1fm8-tq#kU{weW5?1)DH@-&6c$%3;6eaaRXxM zq4yj5^ovrKC7*}Rey2aWO27Ia<@~{G1=AyZcXz<6tIzy_hCsFgnmQE@+=ht#ncTaU zOrvv91(DzJKMaGD2GI`+kb?nucNQaWkmbPmi!~QZ%e<*4cp-po!a%BTceq*+dqY%sq7EKtm}Xn;seA2MRnGokmpHt#*q` ztw=zEe!wZw&j0d*4_=YT)sA78_jLv3e_4Q0nUxacW7? zFQ^!up6gKVnF+efu z_RW6iS@2wAY_yeU!DVbPe_7-2!fWCIX`COWMnT(m-@SY!@>QEC#^&P0y{pJN`Xi8f zs3q*1)lrZ|SKf`wAc0}B-~9`?#-FBM!6cX`O4@-o59y|pTYIhir^HK;MctJ*Chko3 z1zR(YJYCV?k}QI?#+RmMPYo)hYal*`0e+Z3G{WeCaa9N1Q^a2;6qKULqh@1(q481V zh<54ef1eQ5nNP0mP|N=-%w>H3hQs%KY%9ijZzim(;^4$NKMQ>!2T)^v*2+HpBlTwu z@Hi3Du|P@L?;%e~h!>pUJ&;`|uCAX)WAk(U_4(1h)@R4g%}PYFbp$hJPX=cNfqAkt zPGkLWu-?80y6naefFSc90NNL%y3ULj9hsAT^j0)Z%B~XUCQ!5`6=CaM)!pmEVPTXr zHLwVu(Q5{%9K{e{y)_7CsoqhKTj?)`Da@Q(9aToBAU4)Oaw$ubh>ppXx0nLwzTZ%t zLm=G-@!stTkBd*rI`w_N`6V8eY9ya&Ca*5`+2nN26qkSgCx88b9~Tn)01<3dZ6H^# z_KMqCA9TJLTJuj^BG$RrM37OB<%owVr^!Ex zNx6MM6Yi4N=?PjBC~HL3*#AtT`zK&i=1){BUP&r!A4U7@W8sECPLb?CS{nKo19G<< zt2WyQE)mi1#wS+3avJvCzC~H0Ojf14f8k6u+fRFB(khzjjG#RxUPAPzu?63YHKLZOKftR&?6|m@X=@mY9mm)l!Lg9htY=V zTZ>?k>aSHJ`RT@QY+TciT^UPnyZP9mq{2ns9-p_OX|A+UdTT;Cxe+V;qM?9&v`1iN zEU|X&rC5p}GjXOTTM{1hm}|KLX{=7+^|H=udgES&|Jwq#vrSpt0vX2l`aT`Ql7VQB z;(LdA?o~qG)XEs9678qssan)xZHNgwn;#RGp6k`T=n>*cdX_N4$ejE%^O$TdF8@_f zdpLY2EDJalpM&N1%mN@e&!e{2C&Z@AH!a^@*>*7HRMxK$UugFr>1^W08^!2tiaWD6 zfGO)Z5M?hB{$ly%0s3SFR<^S$z~jFbL&wEWGQfSJoVsBEn~9Y{QgM(Pqp9hQO3-q{ z`Qu=fB-TS=8ok`Jkkhwu=2N*$42ZT-J3WC&{Fl8L&`Og`Ik_9^ou> zN@8Ux>Xz<)?y2$p0YF^_bp9$Kb1MD=TbUC*`IU+zm`m-7jsa zvgjpt{_(ZulU#5Z(h%c~CVP`_;{T=_s?*s6)Ocsj+D->Z=7s%g>$lCDuucmH(e}uc z^rp%2Lz3bM!9zAgB~W#qCZ?g+A2Yu$r0;B0m3X_9x4p@Z!IEs_Rcql9kiR^7I(=s| zk3L^M8Uu!%n4P;N|K_bw7SM?cSBPz3ili{la~j&7q`KFzmjSP6a4gKX-!ZX&8`xRh z90WuEXxN++EA&rDM_n-LW(iT6gWaP1#V%e&{R&_ad2RUzwyg=jBWmf&kYg2_Q$!v4 zG2^iW#LGeVZn+i>0HXwB;LfkF&z-&YTeG*a{ak3>%a3Sz z)B{vrsxXKFDH}5ilEXITd2hJ>weFIB%D?Z9zn}$5AlB4SmC~cr1#_<813V#;y-P*x zIzaTAV{)1bOI-!=Pp0#%_2vT0{m`amTv=Xs@Oe1FcwNUH@Sr@EKae^4J2}O3Y*8rh zcEyci4Z3W6Go6=i(OEg@T2$IdY&x$XmH+`}{DzD5jVRYF53??>;Yw#gbq?LtPj5GW zN~9RXrn>b=eesBXJfL9k>c+9nV={B&+YXpzUzjelx9fX=Q;s!?=G#$xGrF@GFi;WM zrdrn)VfLf}OO|qbKiV{<9=?z$;iig-9u-PMtQ+J0Zsqis{OHJZ-7H_KEa8JE_fT#v z&TA8Q9yj+c^A)v`JiZ}`%0wUB-yFSOheu;bjGSyo=RVw3dWaWO1)-`Gqv0O1$vizc z^CkYv&IZ}X?@j<``O1Oj+3|eQZYUEaNyXtTxZ zeIfVtVg*&tD&vpEi^e+)-@Rby=@wlioF3YBSbbwM8>!BX)m^6F{lni4d@b+j1@wov zgSPBSu#!L&x?-mM-ETv481!B=J_*d!V&A>kAX99f&+C%*NeJbLRTB1ApZw*KqBFq( zd4{9X%4|{VV?)_ZUij~DLdgmmnd{b;RQF0qeTcEr+@fJk=ou*w^8|M0zS{I$xZ*du zDQVBX{eiK!T!I7a0|&es`)jjDJGz(=)6%_m0jaC#YIdpW4u%~w3*m69xx@8rA)}^^ zCTBo?x)to#=jA)`1UL(e=r2Q5KloE!G8?bgf773E<{vD+!>ka}^`@78V}%MfYDLLS z;_TFuMKB!wPs4p}q3@Wk!Xpmws2CalSxeeHDF5kIoC(0IM`JwUQp#bEt@{9F83B7! zI}Ov%_DP0gR1W)!U!je$<-2#3ue|$tG$VWWkwW$)Wmp)O6 zH&j2$$#ZHJh!nvr^fc6l3r!tpO_A!~Bg8B1TEe!gF7jk0OQA7RB?G}(P3GLTuiqBk zWKA7)7IJoYN_X%Y>n_$kkb{^$^D4&W9Vj4zVw-57)ItuYR#hOCfxX^M9h?mq=uBH} zUcOQ}Di^f)+xre?W?O7eQcwo@sF0cSr_4TFn1^hO77MvR;CAB4R6$a80H*xuo60Y`%dCbM7B zHx0*n{cVG%atMFB^W#(zvKq~PW7Qxe$<3jDYq%T{;#XQoz}D>rOp6iz`17Z9NCO-` zWs%;zZLOgJP&P1Xasbc|HQG9k>xJ%Fn-BW3Tfc zvN-Y4Q_IYc30gPwGVx)u!K9*kkTAs6JsE=YzzN17^q*o&c!zs zq*>5i@S@iFJi^oh$^g*^!v&zXwIf)NA#34#Uj{3MtWwBZkw z&SvVXCrO?o*Jwwe$PsF->oT>q?Cv)<+7XNncA>=4(S*>{6%Qk2UL%9E6ph5VI$Dc7+=kf}EFH}rc_p|A!{jTTlB+?8 zPVrg+eAdoA7|)-v_!sf=D}jMG+@#M*2rSA+ont=vJpN@#BS`t=>O}=oDvnMxhl3nHyJ08--0>XZ( ziRYsfYgvv%Bj--Bbd<4lc34JOX4vtDc%R}LM(Nh{FLx$;FnH#X!}vpE?j%!*>XNXc zJ4NH0AO^~b$vqN72JT2FCMD-=Bk@-Mc;CHe4o9F!nrRr+g8Z3zG-4;e8GM^-mEG%H zD5;6Jdx+_$up>409CfIuZ1tt@w%4{p6Z>{u3hGQ-wCRLG2NV9~w$(s!J8Pqhs<9(k zMJy$JtER>wl?;2(gtc*G>{O;Yr&{Oo7fpcron!k}8h_s6hD%6R(>qMH`-gOX9&>Zm z0A^U)d@p-c5GfFiGU_fb@l&2#`RHyYg+8=T-Y4TvgZ>0c;4=3P!CA0%hANn<=;Kt8%a4=7*#mv8 zt^4qL9#%3|mGK^#{Dm|OH%C4pd^6N|!@%bDVxyIclC@*y^+v_`FFvQ5h5;b2SwMIv z*lfHBGr52jQ^dHB{a3b^4Y{|iy|s0v!K`iC&$YEgk#+pPWMdb@LN4@|Ls;%$z~DW> zz@K}3fZja>STVp5%TyqOCFp;?d}QE(!5aAxz$yRlq8vPZuiq|iu6w~;IH2R|y#xaV zr`4McZb2mqS!v>FR+SFcf`}HuxPSWQ@%+?mLy$Nr2iE3M7A=k^Gl{GeqmbM^&s=$L zX_)8Q_MfMOBFw@7N^OOF64zSI-9Oi4#BtH_xTI44_fMGbsCM(*#{4WXpHT59po)Z! z?$Z%cY<#7M_JN@;KQ5McF8A-}D{`9}C)2%>bI(4~f-RZfuPQLnjET>+ut=3rHQ#8kCFEw@co3B|- zR^OU3{1?Cneefq$kBc~rwQJ9Xmi6{fSEo>`yN8EzlKOM4&Uxr@tKDPEiUHT?Q)w7km|d7Ke%KnDz*-p+UhrPJsAX z-3^pHxB=iUH!SmL&O#1e-?+#B)E^*Bmz06!xyPad;BXT-b3KYBO4gN<^gEfc=4_y~A^7M8tK zqK5~wQb77eRYx!OX=Q{IMZ(-Y8N_uA^WSX&fbDHs3pHpW70fMOsB~;LMoI>_W`Isv zu6THJeTlvd(J0L(4w+B+-ma2E-BEsGJ|H*A?WA1I5&#JMrUpuvRcw+QB^&@?ul}^t zziK7_5><+tE1hgWcBKt$lNVR|kRBMM&nBP|U3N4DUP>n=D3%NETsFiT-Wc5^YsWXo zYi`o!7%xe-MJj;F#?eL%dxf70wv>klipFbuDZJjIPfAnt|%-xR~Y4$bllgm)1G zIHww`Zagw*j1kxkrld7MwjBX=5D3XH^Bq*7u2G7?vz77U7QxqbuRntb3L5uBYs!N} z`3G&MY+h<msAajLYp{_ zf3CD3ReHzU3>I;h>K?C4`vh`zsvK~0C4PuXaDUgkr{r?VClojGSCr^DvK!#+Utc@S>s)Tb zQCu<3M@t8L5cqZj+|JFg9pRD`DeO?;8z)^binW_a$e!ZrKz~4l>yA7hw*gK(q=)XK z-G()9#T1=My^?J3D8>B=7pnr>^gyYcJ7|FYZ7m;iYT=V@jTQk~Omi&v6Ui|B`TIlA zcoN~&z5|DGwBoSL6$HuInjRA2t&yxP7n=Yg%!?ykYusr#P*XLVB-JI1)rrNo$HSML z6_bTeT!Z6U=H!1i6^^3souByN6GK;KQ^%i@Xph&O>8v&$JKo!ttXwqh8eF61PTKNU zj<#0@8b5ZfmBAS?$>=Rk0KXjI36RV{2;;r7 zp5H20vG(gF(!qAJi|FA%ON6Y$ekf3M`EMna18F_7pG#$p{}srB8M3wHycAc*DSvvt zC;RkunkdlLNf0lwUX@%s$bN4VmuBNp1ExAkkMB5YVz1M%e>8EIEcmAZcm9bs?@TJ+ zKL;1T^lIF12|Yhd0=aTXu_x?NyA-|#NLIdWbyNi00lzT?MWtc+dP#nld_%XEoP&Aq zuX~IrgC+^N0~SJY3&~bxM7IdDPiR|_&3da59tOZ^06f!*IsVlO0C!>ZV-bqw!U0Q6 zXBVJzN~Lw~JbrvE+UHC>gwfLiz9fj)9+emt`b+e_=cDTvZI6y5OyrG;JbVjnstkbu zW;PHi&bcxn%?+J7<$q;iIN^j7W47O4$XR{8{$!*2EEMMu7NLKKRv4C@(HJ3#VheuU z96+>3q&#VcB0Jn1)Hiql+Iyt;6o;v0-qjxh*-h`PM(f6nL*S*(yJP8Yjie=v0s>#5 zg*6=oAh#7k>;xl@kWD}nNrG$BtL%F7bnjMzK5P|)kAgi;BB5~OTlF8(y3;%l3Apq2 zt*w0a0yt@gjNdC1~zO<41oKMZpv%K9nZY}!V7n!5!)vOy33N|ktzXZc`f( z%Y(y_3F%B$l^ueGpEEbChI4?#E$V{_ll;2tC#vYoe4fP7aZ@X9j7Z6!Sl)=^)R>X_ zsF3TJbb`Z~XU^&FXNs==2w{YJnUWF&#wpy{Q|6STFSr*oB z=?JA}xjD$s<80Lh9z-}zAxa$)vwfc&X(PjF$&lL$`Wg?iN?|UHJ}!W=(QRtE2$TNm zte_fQV2gfiixp$#XH$DDALyHs3)*n~dpn3EtrgW*TZ6t4%-)hvGsbReL?71BjLDqMjxvPG67w`_tBGR(mnuA3z(eW9#8GKZcp-D2h_zE{}{8fX4Xr;n({yEAuqe2@~q07{8M+?@AL;qV#9&vIrlfqWSLc(hdR(3xzkLd*=dASf9elN2rK7Bi#1qjU#ERAb)(;4kGq8J&V5}z=)2#r#ra&0~ zhdg~491X)xM@?_6eD*DMc_<)%t_`U~34riHaAfeIv1cf@hX?_zr)B^7H=|+-CE2_f zwVr*ld^q7EaU~Z}xpb1QMbh(mNreLhT4;7R&Lre2LP#ewzVdd6`LiPk>u2F11Xu})}7ADUb;e?zUM+7yMx`9zX!3RqIT7s0+s``$+;fHj1F<1SfR-|DkARS zf~GS!l=}^iX?!J*_0-<^sJHUtc@Dkthp#H?E4bW7m1$-p4lQw^mgk3ux4Tk~T2c-} zy3q=dwB6c~dHp(nsCH{UNX2b;?R_tQX!~Kdzsu`QOC(iCs0hBg&=j%2So&Ke`yrXVIVcI83VWW-agRxeSK$`?ydkxx#^v%%TV&Vz%f81%E4W z!~cFz)}pLiyAsKQzfQYo^L}Pk?K^Jh<8y_N-Y7d_&%pAJl<|5;&7q?i{(YZZe3@Ymp~a;I@RRjzt=37d%FEJ_zk?(H!&~`+R=iNF+>&`h&tWi&UNxC` z*}`wqJz37}H^&c%PyT8OnX81Qx}$*Er5Hu}{2R%%DbtT@t+{+vWeevNomA^w>r!@; zQ}z?{jZ;c1W?Y`ByLfHu9nqm=&s-)lK!((hL)1xUR2JGU6^O14TR2r+Y;F0vZ&80n zEVy<1eYMdJxiI|w4%g1@!>%c=*2vN%h5gU+#tJNw65q~8*d^m-Vz-Bd^p?cfJYU8& ztBznNS`x(*lZI$x=2p^wn=G2{EIzL`UgEivw&|4c#r*Rtg`$V}b}C-?C0 z`$`T_-*MhgVtjCU9hzsZ?YuIwcy?)3a7(Yz+$QMW!$9jlqijC5i!~*h_4=3#xMYjc z0hQnmp_Vxb>k#nYCTQPH*Bxn^J3$lw)O>hrF*|58V>>sjOal5a!XOXLoqs$u&3i{SXoS~DqsT@&x#%ZBCpY5u@@m4 zSY7*HHKb)_CQ2&^d~o^w#Vdr|M=0}SSHVtr%=*muLF_}5r{-5huZd@HWx{bl6`nLw zW-m?VZI!h-zp9(PpQHNnN+K23^I%)UW~b+saz=VT?l>}IPhTL^93S-oKb(Ih(tLxp z{sZ4;uDQ_2M$|?`2b&0Z0`xN}Qy!`w_S+0`pH{U&#dh6|^1$a6T9!Fm77IE~*t3B>Ea;5=iX5#MIbhgNMaKJTFYITzL6-0&4Q563-)n}g z)HdtSMPVv07-@9>8L8I?3HMEv;>FcnE$QmRDR*liApwNk4wWq@T(Y_g$*k4Ze(v)) zXhZ^i^R@cl-pk+2inP0nUH2O-mhZvdEL^w+ zRuxRj-W(80)qi>#RAXfUe^tx@JPVep8~}sV8o5R9y+#}QU(cYkV-_P>R`|gzl1akR zu;#R)xGw%HrOdnvBl%6HyyOl`H!4_4yd0A+nH#XS510T&N=%|LAbhbd(iA9p#B21` z`z7qF`(B;6T(_&N5LD^w`HDeiDV*#}ATgIIlgPjJR&Pm!j@2|N1`amw@6ioN1q$jlWaXG-;!yk)_oXJaErL}9APc` zkuBTi0MNQ6$#|MXOHjU=kV~UFD+AAq#jX*2pQ`j&61f!R6?>F&0u(hn8t1fV|cH-=lTDS_rv?)olkRc zANSmDbD!6B{?6Z`fih9f@{>(J?k@*#_mMt{B58grzbuP z+UfSDA|kRBF50tY^_(fxU;6=?NW4rTu=NC!1abeLoCW}YL$i1%ujvo7mp)wRSMkJ> zA+LwmQt{~C(sWl#uoAX`iEE%+)QFI-svV*d33ZyNq9#vrz8?ZEnx%Ct&TfSmD5P;T ztED)4u^)5NpVz8lHA;-P;Tbb;VG_j-vGM{JzKyQ zp1_t5>o6kast8F?KtKSnO+Y!61bnY9M1AE09v2sP$qIxoh}q!PFbDlFltC1JK;jz* zP3@PrJEPJsjNHvAm_6&6tz%=DAATwbA^GyHpC(}RU@Y>b{Gd)aRkOCGEX4o0fE1Bm z=m`abu*;6~iVb}lZf}p!2PQz3(S(hLzRDys9&&V0htLjqBK|ZMQ@;)%>5O4hf(RQ) zw8OD?2v-nfQo2JlYZ)2EA@?3}_g>5PECQ%=k!}L4>=m@;4`R;)@#G4$T0#MaMYkNYOU@5DU7@0e(U+RR^~Pb{M^9QjzPV>mwIsf1vNuxU zu>clOFZ)p)_@{^rPHM*3O=$xmkGp^!u!ZH6c``L2xN`>BH4|Aj#YId0vh)dTALg>B zW_Q>zfooZwcoz^d{`wprUH0B_~Xno|Axbh7~??j z_nb0vN4h25G}ZO-L0G-Lv|0C1XuF=YdD)6480BHSrDn7N9>s7n3AK zzY-I*ps^me`#4R5Kac>*-m^gYv7HD{K@hpB89AiY64oEC)=lUf_jXMU+DaesT;;Zj zvhT=n6(IrakUfh((YVn+2WgkI4`Okh1nkyg)#-3f?^@+Mg^_^(?PW?|C|s09_*FIL zvr7Lq&KIyRw66?^mwOdkcQ!ufXLSFB>A9f`pzLU4cBkj9G}0UVJM%GYNl8gY!eQ~x zw@*XkK;~e}o^xcS`!~}(`v3evpTCcFY;@UFfVE1Xj}M=zz+vgvVN+l>2_$i)-V($F zr`Xosju=4tKrw}`8o`!b@D&~%I4N7t0g6+FiysfRE`If>ITFOoxRUF-)wc`l@|IW= zdWd$g`Mm+(iO9>=W=3^~^`q26d&itIR~E*zOhk2iB6!o}%4i@@{&gMWL=l^d1p-zR z>Jcl;uMD`Pp06)6Ava$4ZB^N$O+HUKA0WLPI%*y2dKS3 zVBxF{q|4^qAU&;Z6peV)wS|PurM9IsqP{3+&2=j;XM4iou1{pKi+dIv(bc| z2p(0@&WIKL8UM;N#{EcrFKBrZkM{mWw8vLL>A2$xqw=d%{=1HAhO-M- zf%3Lx93ERY2cqvjHYaTs4BPD;bbUEKAEQ6>nu^;k=r>d3B67}}K5TwX^Onk2%%h1{} zyxZX83%9b;&9)Ae4z;POZA0LqrA*_3sDRbDe;TK-Trkjt@Y&@!T3FUDE5RtY=E6P zdCydEX@y4ViEZT;+wdNGdP|el3~kHPY;m;jDU3C&Kx0fb=vCFQH)HGHQx((=f8MRs z)2fRZMfaty_dFq0B7JU9j1!qn2J=;T%|f-qYvk$46Ne;(oaEy<^4+}IS<>l-S?Kcr z7@UfLNHk5W-jrgx$)np-RTU-t9B7{ zcGYZy2$IgCsmlBVk>lSRQFW!nz?wqtwq$Lg@(c2@gxX;_K5aJb=KbNUKYJWtfbmg9 zK$Rw*LDH8?ewv9zLmFcF!_I=rvY=WdVe{Sd?K<){0f05)b>8g&15;w<9Z~rpi0z## zAN%VyxZgdGDN+WJn(ytm=sB?!1}ny;&RdNE-Wm~Np+5t1s3`IJVm%zhI`sV8SVJ2x zd=pFs4<5Z(b`?z<;8vi0AViR*zI&ib`65zT3|6lJPW!3R9aPXp zN1jCfC>#}j7+do*3SGyXg^$%;w~*84wfs1B>d`e3gnhgI4}6o@zW@2cev zA$KP$J++4Cg0X)0Yp)B^$CP$}NhG3B+RW;lcLzHJQPhXm_(?h^1nt?tE&&g8b3Opv z^=9Oa5dgZgMV-DSaoZ1^gaxpqsulhT7$WwH7z{u`2R-;l6Z==ul*z-f+2ZP@<5>)S zAxFA9SdTBpN_*?*eAelsyF*>JuH34Fi4&_VpCHovvnzr!if0FV`o$ahVnR^d+wm+s z@>S1IR8{NK1ldbOM{$9xq0-x|?H2X-@T@1b4=BP<*L0D$Pw9;(9AXa$e|sJOQneGG zkbkF37I=N82LD9Y=?i|7OL)X58u1120_A~BCnyg!_@&`l@~afUsM`XADfZAna_I7v zTbsN=;1?ug8G19{5B8YPJyK$V{T%l7;1dD2(dd zxpRlr)Y^yYN=hF=?sU&vF4qR(_i7c@zng0`Ua;oA_t{|HuJhICR4RJnH{h{r<}$&Z zhSvz#6;OL^u3*!pIw_^qblkp;D1!|Gkk$tADxSDRZ!l*VQZ5u{8!xI*rMVilD!8?W zeZc>KvIPHVI{i}TCo3(KU#|p{zgDn!ksgXOnt!45Pd|K#8}7}ojz~E@#+LkgxAno- z+y7}drxdw53w0GB{TG2`v~1{vSGv~r^{NvJ+zssnr?DKaULyJ~-q|KQPIQf->I4}- zw9>!+W$w=S{?2`>TF9V6{Z`rxMnx*<%3-<3Xat)6QQGdbLB(a%`bn0&k6UxdLcdX> zI+a{Z$t|p453qEWV?;;ww>Ics5I<${;!JNJWr-YKD8D{SE^vOrwTWLGYw;d`OI!CO z4F(D?{M_JwI0BLDyQS=v>1Xn7A8)N@aoXMz<>&t28eg4gFaIK_Q|)HP z46Q9tE8Fx2Mad@J{Ux)U@J6*IM(8`-O7Jehys7y)MMT&Q*P8+F))$GQc;Q_v@C zJ*w)sWUqX7q>TF3QWAlILXP+To$$C`fzTq7*ZcXIpKl?;j)AVd6)(d%{ddtO772+~ z3oz%;q^1DZZ2KSa_E7IrxDB6Q)8W6GAMHaM$D1!$lmc!wiWIU`=@T^fXJ|)X-62Bh zp>6nmK(t^+MklL2x+ShPdF4}h5M7u#`P%b;(!@v6xj zh}h|P;E;m_UVR!FjoAz%*@7m$^n2mHuY+#Rxz^qOqsgUyhx`*SJmGaY3slx{$Jds`lPcu>a3RyNqz`%3-UjLQel{&BY)Qw>@{p0D{l;2Okb5><< z_g}eFFcOEkE?xlB>kpl?dhyjNX@@N>bQppD9G zN_u;MV60qvtxy=gv~E2k;(AfJzU$mw|C!{Nt0nt__8iScqJ$IIPe?xX`+a$G0hxWD zR)YMJce_4iJ>QY0I_(fhVV^Fly3{^6|6|o--==J|&Ta{fm9*(KZ9pZ6)L*Oh37`v1 zB1j31?gPimIUl@`CY?kV)@YQI^P(H%AIej=+_-C#^2)sR$C5=Qb>)NL)8lnOCeb^!fY82U|FVt3 zjE#(LK#mF(&?KLX&MiBzW#5_q{PG5j**ZN)9gN#p=W~Esh*~q{Iyv{FISmD5qt|-t z<{AFAQ(lwb?#Ompe+(qsJa%+*o2L7}2P!+XML>)@J(W{LTIZpa84-p+w)^{%ehR=v zca&CElB=sVpjauFs)8np@_My*tIN!>T;qdFUGuau{XPJIdVr0~-hiuqS%8HwQjP*n zX9%GyG3DNn0AA&C^+#fF+}iS->UCIGKzc?7h3}i_U&d$E3JJarWNh{X|5WJnUZ$<( zT=-k^8dncQV5oM)fB@U_!op9#;~`RNY^#g%B!XrIk6&zGNa(nwO z1jahQzJ+<7w@9|JsszFcM*g`6?=r?4G*r5Eh@Gr}EC4}K>rE?Xkd&~JSc_T`r-T$^ z1t^%S6OnpV1U|6!^R&`iddkq+W9%ml_P;nB?lZfac|I?*q2T^~7|pR!j9-6=wZ<(( z0r|y*oU--8O6wv$!AiZhNCipi2Vq*#K9@=Cq^f^`uE#<`_Uk9XV^1439eEt1hQIvg zbHGwfm{A5ugKKUJpD;4`0>gq_kgTnD2mFfje6zwv9?QoygUqnOIFMczB=?He&9hY+ zr;)q33NY%;#UZGW>b1U?72ExEaP zS^I%Z=b)hs&e&G71XNjDmNqpShq}2aHwIWXXbHkf+E8K#ur3&lx!wi>i7>$l!CX=! z|9{`fV;}QCn$Oe>M6%{6$4225vFm)4U)cUAp2 zLdU-b*M7DS9IPxWw7#@Ni2F_wY!G90OxZ8^=|*Gk9r@dC{uIhIAzbmB5H3f3@)Y~q z2_xRPi^tUVT@wPk?EI&uLpT4lgveJ}PL7V0Xk@8oq2a}mG=pDN1*n@4+e90!yF+~! zd`4Jg&Q6^O7|l)wW^4Sb43TYSmJe37&VxbP-9U&J^Y_Q?+HzcgJ97HMEcUN7p@ukh z-$4vi(;fFYA?c0@TQpqEqUf)UBeC3m1zuO-GX@=3Bv-c3TVuf(T^8}Obp_?jSjXv0pX;m9{F(kxiobid2 z<@Hyv+&vQIVxKLwQ$HfRH5LC{!H^6;b*Sd6Zp;flieS|1uQpd&EHo; zj6E-DW-?zG_!zAG*aZfxSoR>5Chiz{OZ*WZ39pw+uqd1IsQBe2q!dQ(>zNZP#096+gg+lip;uAsk? zrxsi3%Omwqssx?EuD~*GT>!`m;$&>nYfNtzUKDbdM+q8JPT3^!c=5Vy_mm5@hYZ_a z4o4WxDX}DNJ4&rsPJQgE#Kf2eq`=}1lT{9R<OG z*o}-i^=IcliD*728Ey7WHqYVASrx*3<9;~4dvGg2kliBrWjZzp+>jZnF>hF_)HECz zjne^nZg|SnFLS+iN$*m0bPZJZ^!nZd-5lM2;{(^x);45ZH91B;zhQ>5o2CI5dJ5IP zd#=8R+M3a)|6-o(5aDNjU0Qd(g9+WNw{t?^aYN0fSGR*z#SouNdW@BA;7WrxtZ47_ zmmVQNc3b9biHeYux3~9Yl%1<93OEW>v0jXs(Hv_lfj0Mt0Dhm4S3qC+=@Vy<=3!$=`(l}bIS!S z0v!&FDuATq-Cs literal 0 HcmV?d00001 diff --git a/en/device-dev/subsystems/figures/nnrt_dev_flow.png b/en/device-dev/subsystems/figures/nnrt_dev_flow.png new file mode 100644 index 0000000000000000000000000000000000000000..612ae5fe5abfb3df5936c314672cf1877ee5404d GIT binary patch literal 36978 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 NOTE
In this application scenario, the connection of the RK3568 chip to NNRt is implemented by utilizing the CPU operator of MindSpore Lite, instead of writing the CPU driver. This is the reason why the following development procedure depends on the dynamic library and header file of MindSpore Lite. In practice, the development does not depend on any library or header file of MindSpore Lite. + +### Development Flowchart +The following figure shows the process of connecting a dedicated acceleration chip to NNRt. + +**Figure 2** NNRt development flowchart + +![NNRt development flowchart](./figures/nnrt_dev_flow.png) + +### Development Procedure +To connect the acceleration chip to NNRt, perform the following steps: +#### Generate the HDI header file. +Download the OpenHarmony source code from the open source community, build the `drivers_interface` component, and generate the HDI header file. + +1. [Download the source code](../get-code/sourcecode-acquire.md). + +2. Build the IDL file of the HDI. + ```shell + ./build.sh --product-name productname –ccache --build-target drivers_interface_nnrt + ``` + > **productname** indicates the product name. In this example, the product name is **RK3568**. + + When the build is complete, the HDI header file is generated in `out/rk3568/gen/drivers/interface/nnrt`. The default programming language is C++. To generate a header file for the C programming language, run the following command to set the `language` field in the `drivers/interface/nnrt/v1_0/BUILD.gn` file before starting the build: + + ```shell + language = "c" + ``` + + The directory of the generated header file is as follows: + ```text + out/rk3568/gen/drivers/interface/nnrt + └── v1_0 + ├── drivers_interface_nnrt__libnnrt_proxy_1.0_external_deps_temp.json + ├── drivers_interface_nnrt__libnnrt_stub_1.0_external_deps_temp.json + ├── innrt_device.h # Header file of the HDI + ├── iprepared_model.h # Header file of the AI model + ├── libnnrt_proxy_1.0__notice.d + ├── libnnrt_stub_1.0__notice.d + ├── model_types.cpp # Implementation file for AI model structure definition + ├── model_types.h # Header file for AI model structure definition + ├── nnrt_device_driver.cpp # Device driver implementation example + ├── nnrt_device_proxy.cpp + ├── nnrt_device_proxy.h + ├── nnrt_device_service.cpp # Implementation file for device services + ├── nnrt_device_service.h # Header file for device services + ├── nnrt_device_stub.cpp + ├── nnrt_device_stub.h + ├── nnrt_types.cpp # Implementation file for data type definition + ├── nnrt_types.h # Header file for data type definition + ├── node_attr_types.cpp # Implementation file for AI model operator attribute definition + ├── node_attr_types.h # Header file for AI model operator attribute definition + ├── prepared_model_proxy.cpp + ├── prepared_model_proxy.h + ├── prepared_model_service.cpp # Implementation file for AI model services + ├── prepared_model_service.h # Header file for AI model services + ├── prepared_model_stub.cpp + └── prepared_model_stub.h + ``` + +#### Implementing the HDI Service + +1. Create a development directory in `drivers/peripheral`. The structure of the development directory is as follows: + ```text + drivers/peripheral/nnrt + ├── BUILD.gn # Code build script + ├── bundle.json + └── hdi_cpu_service # Customized directory + ├── BUILD.gn # Code build script + ├── include + │ ├── nnrt_device_service.h # Header file for device services + │ ├── node_functions.h # Optional, depending on the actual implementation + │ ├── node_registry.h # Optional, depending on the actual implementation + │ └── prepared_model_service.h # Header file for AI model services + └── src + ├── nnrt_device_driver.cpp # Implementation file for the device driver + ├── nnrt_device_service.cpp # Implementation file for device services + ├── nnrt_device_stub.cpp # Optional, depending on the actual implementation + ├── node_attr_types.cpp # Optional, depending on the actual implementation + ├── node_functions.cpp # Optional, depending on the actual implementation + ├── node_registry.cpp # Optional, depending on the actual implementation + └── prepared_model_service.cpp # Implementation file for AI model services + ``` + +2. Implement the device driver. Unless otherwise required, you can directly use the `nnrt_device_driver.cpp` file generated in step 1. + +3. Implement service APIs. For details, see the `nnrt_device_service.cpp` and `prepared_model_service.cpp` implementation files. For details about the API definition, see [NNRt HDI Definitions](https://gitee.com/openharmony/drivers_interface/tree/master/nnrt). + +4. Build the implementation files for device drivers and services as shared libraries. + + Create the `BUILD.gn` file with the following content in `drivers/peripheral/nnrt/hdi_cpu_service/`. For details about how to set related parameters, see [Compilation and Building](https://gitee.com/openharmony/build). + + ```shell + import("//build/ohos.gni") + import("//drivers/hdf_core/adapter/uhdf2/uhdf.gni") + + ohos_shared_library("libnnrt_service_1.0") { + include_dirs = [] + sources = [ + "src/nnrt_device_service.cpp", + "src/prepared_model_service.cpp", + "src/node_registry.cpp", + "src/node_functions.cpp", + "src/node_attr_types.cpp" + ] + public_deps = [ "//drivers/interface/nnrt/v1_0:nnrt_idl_headers" ] + external_deps = [ + "hdf_core:libhdf_utils", + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_single", + "c_utils:utils", + ] + + install_images = [ chipset_base_dir ] + subsystem_name = "hdf" + part_name = "drivers_peripheral_nnrt" + } + + ohos_shared_library("libnnrt_driver") { + include_dirs = [] + sources = [ "src/nnr_device_driver.cpp" ] + deps = [ "//drivers/peripheral/nnrt/hdi_cpu_service:libnnrt_service_1.0" ] + + external_deps = [ + "hdf_core:libhdf_host", + "hdf_core:libhdf_ipc_adapter", + "hdf_core:libhdf_utils", + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_single", + "c_utils:utils", + ] + + install_images = [ chipset_base_dir ] + subsystem_name = "hdf" + part_name = "drivers_peripheral_nnrt" + } + + group("hdf_nnrt_service") { + deps = [ + ":libnnrt_driver", + ":libnnrt_service_1.0", + ] + } + ``` + + Add `group("hdf_nnrt_service")` to the `drivers/peripheral/nnrt/BUILD.gn` file so that it can be referenced at a higher directory level. + ```shell + if (defined(ohos_lite)) { + group("nnrt_entry") { + deps = [ ] + } + } else { + group("nnrt_entry") { + deps = [ + "./hdi_cpu_service:hdf_nnrt_service", + ] + } + } + ``` + + Create the `drivers/peripheral/nnrt/bundle.json` file to define the new `drivers_peripheral_nnrt` component. + ```json + { + "name": "drivers_peripheral_nnrt", + "description": "Neural network runtime device driver", + "version": "3.2", + "license": "Apache License 2.0", + "component": { + "name": "drivers_peripheral_nnrt", + "subsystem": "hdf", + "syscap": [""], + "adapter_system_type": ["standard"], + "rom": "1024KB", + "ram": "2048KB", + "deps": { + "components": [ + "ipc", + "hdf_core", + "hiviewdfx_hilog_native", + "c_utils" + ], + "third_part": [ + "bounds_checking_function" + ] + }, + "build": { + "sub_component": [ + "//drivers/peripheral/nnrt:nnrt_entry" + ], + "test": [ + ], + "inner_kits": [ + ] + } + } + } + ``` + +#### Declaring the HDI Service + + In the uhdf directory, declare the user-mode driver and services in the **.hcs** file of the corresponding product. For example, for the RK3568 chip, add the following configuration to the `vendor/hihope/rk3568/hdf_config/uhdf/device_info.hcs` file: + ```text + nnrt :: host { + hostName = "nnrt_host"; + priority = 50; + uid = ""; + gid = ""; + caps = ["DAC_OVERRIDE", "DAC_READ_SEARCH"]; + nnrt_device :: device { + device0 :: deviceNode { + policy = 2; + priority = 100; + moduleName = "libnnrt_driver.z.so"; + serviceName = "nnrt_device_service"; + } + } + } + ``` +> NOTE
After modifying the `.hcs` file, you need to delete the `out` directory and build the file again for the modification to take effect. + +#### Configuring the User ID and Group ID of the Host Process + In the scenario of creating an nnrt_host process, you need to configure the user ID and group ID of the corresponding process. The user ID is configured in the `base/startup/init/services/etc/passwd` file, and the group ID is configured in the `base/startup/init/services/etc/group` file. + ```text + # Add the user ID in base/startup/init/services/etc/passwd. + nnrt_host:x:3311:3311:::/bin/false + + # Add the group ID in base/startup/init/services/etc/group. + nnrt_host:x:3311: + ``` + +#### Configuring SELinux + +The SELinux feature has been enabled for the OpenHarmony. You need to configure SELinux rules for the new processes and services so that they can run the host process to access certain resources and release HDI services. + +1. Configure the security context of the **nnrt_host** process in the `base/security/selinux/sepolicy/ohos_policy/drivers/adapter/vendor/type.te` file. + ```text + # Add the security context configuration. + type nnrt_host, hdfdomain, domain; + ``` + > In the preceding command, **nnrt_host** indicates the process name previously configured. + +2. Configure access permissions because SELinux uses the trustlist access permission mechanism. Upon service startup, run the `dmesg` command to view the AVC alarm, +which provides a list of missing permissions. For details about the SELinux configuration, see [security_selinux] (https://gitee.com/openharmony/security_selinux/blob/master/README-en.md). + ```shell + hdc_std shell + dmesg | grep nnrt + ``` + +3. Create the `nnrt_host.te` file. + ```shell + # Create the nnrt folder. + mkdir base/security/selinux/sepolicy/ohos_policy/drivers/peripheral/nnrt + + # Create the vendor folder. + mkdir base/security/selinux/sepolicy/ohos_policy/drivers/peripheral/nnrt/vendor + + # Create the nnrt_host.te file. + touch base/security/selinux/sepolicy/ohos_policy/drivers/peripheral/nnrt/vendor/nnrt_host.te + ``` + +4. Add the required permissions to the `nnrt_host.te` file. For example: + ```text + allow nnrt_host dev_hdf_kevent:chr_file { ioctl }; + allow nnrt_host hilog_param:file { read }; + allow nnrt_host sh:binder { transfer }; + allow nnrt_host dev_ashmem_file:chr_file { open }; + allow sh nnrt_host:fd { use }; + ``` + +#### Configuring the Component Build Entry +Access the `chipset_common.json` file. +```shell +vim //productdefine/common/inherit/chipset_common.json +``` +Add the following to `"subsystems"`, `"subsystem":"hdf"`, `"components"`: +```shell +{ + "component": "drivers_peripheral_foo", + "features": [] +} +``` + +#### Deleting the out Directory and Building the Entire System +```shell +# Delete the out directory. +rm -rf ./out + +# Build the entire system. +./build.sh --product-name rk3568 –ccache --jobs=4 +``` + + +### Commissioning and Verification +On completion of service development, you can use XTS to verify its basic functions and compatibility. + +1. Build the **hats** test cases of NNRt in the `test/xts/hats/hdf/nnrt` directory. + ```shell + # Go to the hats directory. + cd test/xts/hats + + # Build the hats test cases. + ./build.sh suite=hats system_size=standard --product-name rk3568 + + # Return to the root directory. + cd - + ``` + The hats test cases are exported to `out/rk3568/suites/hats/testcases/HatsHdfNnrtFunctionTest` in the relative code root directory. + +2. Push the test cases to the device. + ```shell + # Push the executable file of test cases to the device. In this example, the executable file is HatsHdfNnrtFunctionTest. + hdc_std file send out/rk3568/suites/hats/testcases/HartsHdfNnrtFunctionTest /data/local/tmp/ + + # Grant required permissions to the executable file of test cases. + hdc_std shell "chmod +x /data/local/tmp/HatsHdfNnrtFunctionTest" + ``` + +3. Execute the test cases and view the result. + ```shell + # Execute the test cases. + hdc_std shell "/data/local/tmp/HatsHdfNnrtFunctionTest" + ``` + + The test report below shows that all 47 test cases are successful, indicating that the service has passed the compatibility test. + ```text + ... + [----------] Global test environment tear-down + Gtest xml output finished + [==========] 47 tests from 3 test suites ran. (515 ms total) + [ PASSED ] 47 tests. + ``` + +### Development Example +For the complete demo code, see [NNRt Service Implementation Example](https://gitee.com/openharmony/ai_neural_network_runtime/tree/master/example/drivers). + +1. Copy the `example/driver/nnrt` directory to `drivers/peripheral`. + ```shell + cp -r example/driver/nnrt drivers/peripheral + ``` + +2. Add the `bundle.json` file to `drivers/peripheral/nnrt`. For details about the `bundle.json` file, see [Development Procedure](#development-procedure). + +3. Add the dependency files of MindSpore Lite because the demo depends on the CPU operator of MindSpore Lite. + - Download the header file of [MindSpore Lite 1.5.0](https://ms-release.obs.cn-north-4.myhuaweicloud.com/1.5.0/MindSpore/lite/release/linux/mindspore-lite-1.5.0-linux-x64.tar.gz). + - Create the `mindspore` directory in `drivers/peripheral/nnrt`. + ```shell + mkdir drivers/peripheral/nnrt/mindspore + ``` + - Decompress the `mindspore-lite-1.5.0-linux-x64.tar.gz` file, and copy the `runtime/include` directory to `drivers/peripheral/nnrt/mindspore`. + - The demo also depends on the `schema` file of MindSpore Lite. + ```shell + # Create the mindspore_schema directory. + mkdir drivers/peripheral/nnrt/hdi_cpu_service/include/mindspore_schema + + # Copy the schema file of MindSpore Lite. + cp third_party/mindspore/mindspore/lite/schema/* drivers/peripheral/nnrt/hdi_cpu_service/include/mindspore_schema/ + ``` + - Build the dynamic library of MindSpore Lite, and put the dynamic library in the `mindspore`directory. + ```shell + # Build the dynamic library of MindSpore Lite. + ./build.sh --product-name rk3568 -ccaache --jobs 4 --build-target mindspore_lib + + # Create the mindspore subdirectory. + mkdir drivers/peripheral/nnrt/mindspore/mindspore + + # Copy the dynamic library to drivers/peripheral/nnrt/mindspore/mindspore. + cp out/rk3568/package/phone/system/lib/libmindspore-lite.huawei.so drivers/peripheral/nnrt/mindspore/mindspore/ + ``` +4. Follow the [development procedure](#development-procedure) to complete other configurations. diff --git a/en/device-dev/subsystems/subsys-dfx-hicollie.md b/en/device-dev/subsystems/subsys-dfx-hicollie.md index 90bb652a9a..321bc54040 100644 --- a/en/device-dev/subsystems/subsys-dfx-hicollie.md +++ b/en/device-dev/subsystems/subsys-dfx-hicollie.md @@ -1,185 +1,101 @@ -# HiCollie Development +# HiCollie Development -## Overview -HiCollie provides the software watchdog function. It provides a unified framework for fault detection and fault log generation to help you locate software timeout faults resulting from system service deadlock, application main thread blocking, and service process timeout. - -## Available APIs - -**Table 1** Description of C++ APIs - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Class

-

API

-

Description

-

XCollieChecker

-

virtual void CheckBlock()

-

Provides the callback of the suspension detection result.

-

Input arguments: none

-

Output arguments: none

-

Return value: none

-

XCollieChecker

-

virtual void CheckThreadBlock()

-

Provides the callback of the thread suspension detection result.

-

Input arguments: none

-

Output arguments: none

-

Return value: none

-

XCollie

-

void RegisterXCollieChecker(const sptr<XCollieChecker> &checker, unsigned int type)

-

Registers the callback of the thread suspension detection result.

-

Input arguments:

-
  • checker: Indicates the pointer to the XCollieChecker instance.
  • type: Indicates the suspension detection type. Set it to XCOLLIE_THREAD.
-

Output arguments: none

-

Return value: none

-

XCollie

-

int SetTimer(const std::string &name, unsigned int timeout, std::function<void (void *)> func, void *arg, unsigned int flag)

-

Adds timers.

-

Input arguments:

-
  • name: Indicates the timer name.
  • timeout: Indicates the timeout duration, in seconds.
  • func: Indicates the timeout callback.
  • arg: Indicates the pointer to the timeout callback.
  • flag: Indicates the timer operation type.

    XCOLLIE_FLAG_DEFAULT // Indicates the default flag, which is the combination of the other three options.

    -

    XCOLLIE_FLAG_NOOP // Calls only the timeout callback.

    -

    XCOLLIE_FLAG_LOG // Generates a timeout fault log.

    -

    XCOLLIE_FLAG_RECOVERY // Exits the process.

    -
-

Output arguments: none

-

Return value: Returns the timer ID if the operation is successful; returns -1 otherwise.

-

XCollie

-

bool UpdateTimer(int id, unsigned int timeout)

-

Updates timers.

-

Input arguments:

-
  • id: Indicates the timer ID.
  • timeout: Indicates the timeout duration, in seconds.
-

Output arguments: none

-

Return value: Returns true if the operation is successful; returns false otherwise.

-

XCollie

-

void CancelTimer(int id)

-

Cancels timers.

-

Input arguments:

-

id: Indicates the timer ID.

-

Output arguments: none

-

Return value: none

-
- -## Example - -Print logs. - -``` -timeout: TimeoutTimer start at 1611040305 to check 1s ago - -----------StacktraceCatcher CurrentTime:2021-01-19 15:11:45 Unexecuted(-1)(LogType:Stacktrace Pid:27689 Process:XCollieTimeoutModuleTest)---------- - - ------ pid 27689 at 2021-01-19 15:11:45 ----- -Cmd line: ./XCollieTimeoutModuleTest -ABI: 'arm64' - -"XCollieTimeoutM" sysTid=27689 - #01 pc 00000000000174cc /data/test/XCollieTimeoutModuleTest -``` - -## How to Develop - -### C++ - -### Thread Suspension Monitoring - -This function requires you to implement two callback functions: **CheckBlock** and **CheckThreadBlock** of the **XCollieChecker** class. After the callbacks are implemented, you need to use the **RegisterXCollieChecker** function of the **XCollie** class to register their instances. The suspension monitoring thread periodically executes all successfully registered callbacks, checks the thread logic completion flag, and determines whether the service logic of any registered thread is suspended. - -1. Develop the source code. - - Include the **xcollie** header file in the source file. - - ``` - #include "xcollie.h" - ``` - - Add the following code to the service code: - - ``` - void MyXCollieChecker::CheckLock() - { - /* time consuming job */ - } - - void MyXCollieChecker::CheckThreadBlock() - { - /* time consuming job */ - } - - sptr checker = new MyXCollieChecker("MyXCollieChecker"); - XCollie::GetInstance().RegisterXCollieChecker(checker, - (XCOLLIE_LOCK | XCOLLIE_THREAD)); - ... - ``` - -2. Configure compilation information. Specifically, add the subsystem SDK dependency to **BUILD.gn**. - - ``` - external_deps = [ "hiviewdfx:libxcollie" ] - ``` - - -### Timeout Monitoring - -You can add a maximum of 128 timers for a single process by using the **SetTimer** function. Adding timers will fail if the number of timers has reached the upper limit. - -1. Develop the source code. - - Include the **xcollie** header file in the source file. - - ``` - #include "xcollie.h" - ``` - - Add the code to add, update, and cancel timers. - - ``` - std::function callback = [](void *args) - { - /* dump helpful information */ - }; - - int id = XCollie::GetInstance().SetTimer("MyXCollieTimer", 10, callback ,nullptr, XCOLLIE_FLAG_LOG); - /* time consuming job */ - XCollie::GetInstance().UpdateTimer(id, 5); - /* time consuming job */ - XCollie::GetInstance().CancelTimer(id); - ... - ``` +## Overview -2. Configure compilation information. Specifically, add the subsystem SDK dependency to **BUILD.gn**. - - ``` - external_deps = [ "hiviewdfx:libxcollie" ] - ``` +HiCollie provides the software watchdog function. It provides a unified framework for fault detection and fault log generation to help you locate software timeout faults resulting from system service deadlock, application main thread blocking, and service process timeout. +## Available APIs + + **Table 1** Description of XCollieChecker APIs + +| API| Description| +| -------- | -------- | +| virtual void CheckBlock() | Provides the callback of the suspension detection result.
Input arguments: none
Output arguments: none
Return value: none| +| virtual void CheckThreadBlock() | Provides the callback of the thread suspension detection result.
Input arguments: none
Output arguments: none
Return value: none| + + + **Table 2** Description of XCollie APIs + +| API| Description| +| -------- | -------- | +| void RegisterXCollieChecker(const sptr<XCollieChecker> &checker, unsigned int type) | Registers the callback of the thread suspension detection result.
Input arguments:
- **checker**: pointer to the XCollieChecker instance.
- **type**: suspension detection type. Set it to **XCOLLIE_THREAD**.
Output arguments: none
Return value: none| +| int SetTimer(const std::string &name, unsigned int timeout, std::function<void(void*)> func, void *arg, unsigned int flag) | Adds timers.
Input arguments:
- **name**: timer name.
- **timeout**: timeout duration, in seconds.
- **func**: timeout callback.
- **arg**: pointer to the timeout callback.
- **flag**: timer operation type.
- **XCOLLIE_FLAG_DEFAULT**: default flag, which is the combination of the other three options.
- **XCOLLIE_FLAG_NOOP**: Calls only the timeout callback.
- **XCOLLIE_FLAG_LOG**: Generates a timeout fault log.
- **XCOLLIE_FLAG_RECOVERY**: Exits the process.
Output arguments: none
Return value: timer ID if the operation is successful; **-1** otherwise.| +| bool UpdateTimer(int id, unsigned int timeout) | Updates timers.
Input arguments:
- **id**: timer ID.
- **timeout**: timeout duration, in seconds.
Output arguments: none
Return value: **true** if the operation is successful; **false** otherwise.| +| void CancelTimer(int id) | Cancels a timer.
Input arguments:
- **id**: timer ID.
Output arguments: none
Return value: none| + + +## How to Develop + + +### Thread Suspension Monitoring + +This function requires you to implement two callback functions: **CheckBlock** and **CheckThreadBlock** of the **XCollieChecker** class. After the callbacks are implemented, you need to use the **RegisterXCollieChecker** function of the **XCollie** class to register their instances. The suspension monitoring thread periodically executes all successfully registered callbacks, checks the thread logic completion flag, and determines whether the service logic of any registered thread is suspended. + +1. Develop the source code. + Include the **xcollie** header file in the source file. + + ``` + #include "xcollie.h" + ``` + + Add the following code to the service code: + + + ``` + void MyXCollieChecker::CheckLock() + { + /* time consuming job */ + } + + void MyXCollieChecker::CheckThreadBlock() + { + /* time consuming job */ + } + + sptr checker = new MyXCollieChecker("MyXCollieChecker"); + XCollie::GetInstance().RegisterXCollieChecker(checker, + (XCOLLIE_LOCK | XCOLLIE_THREAD)); + ...... + ``` + +2. Configure compilation information. Specifically, add the subsystem SDK dependency to **BUILD.gn**. + + ``` + external_deps = [ "hiviewdfx:libxcollie" ] + ``` + + +### Timeout Monitoring + +You can add a maximum of 128 timers for a single process by using the **SetTimer** function. Adding timers will fail if the number of timers has reached the upper limit. + +1. Develop the source code. + Include the **xcollie** header file in the source file. + + ``` + #include "xcollie.h" + ``` + + Add the code to add, update, and cancel timers. + + ``` + std::function callback = [](void *args) + { + /* dump helpful information */ + }; + + int id = XCollie::GetInstance().SetTimer("MyXCollieTimer", 10, callback ,nullptr, XCOLLIE_FLAG_LOG); + /* time consuming job */ + XCollie::GetInstance().UpdateTimer(id, 5); + /* time consuming job */ + XCollie::GetInstance().CancelTimer(id); + ...... + ``` + +2. Configure compilation information. Specifically, add the subsystem SDK dependency to **BUILD.gn**. + + ``` + external_deps = [ "hiviewdfx:libxcollie" ] + ``` diff --git a/en/device-dev/subsystems/subsys-dfx-hidumper.md b/en/device-dev/subsystems/subsys-dfx-hidumper.md index 1060ab1dea..5c6bc09ecf 100644 --- a/en/device-dev/subsystems/subsys-dfx-hidumper.md +++ b/en/device-dev/subsystems/subsys-dfx-hidumper.md @@ -1,21 +1,18 @@ -# HiDumper Development +# HiDumper ## Overview - -### Introduction - HiDumper is a tool provided by OpenHarmony for developers, testers, and IDE tool engineers to obtain system information necessary for analyzing and locating faults. This section applies only to the standard system. -### Source Code Directories +## Source Code Directories ``` /base/hiviewdfx/hidumper ├── frameworks # Framework code │ ├── native # Core function code -│ │ │── include # Header files +│ │ │── include # Header files │ │ │── src # Source files │ │ │── common # Common function code │ │ │── executor # Process executor code @@ -34,14 +31,14 @@ HiDumper is a tool provided by OpenHarmony for developers, testers, and IDE tool ``` -## Usage +# Usage -### Command-Line Options +## Command-Line Options **Table 1** HiDumper command-line options -| Option| Description| +| Option| **Description**| | -------- | -------- | | -h | Shows the help Information.| | -t [timeout] | Specifies the timeout period, in seconds. The default value is **30**. Value **0** indicates no timeout limit.| @@ -56,14 +53,14 @@ HiDumper is a tool provided by OpenHarmony for developers, testers, and IDE tool | --net | Exports network information.| | --storage | Exports storage information.| | -p | Exports the process list and all process information.| -| -p [pid] | Exports all information about a specified process.| -| --cpuusage [pid] | Exports the CPU usage information based on **pid**.| +| -p [pid] | Exports all information about the specified process.| +| --cpuusage [pid] | Exports the CPU usage information. If **pid** is specified, the CPU usage of the corresponding process is exported.| | --cpufreq | Exports the actual CPU frequency.| -| --mem [pid] | Exports the memory usage information based on **pid**.| +| --mem [pid] | Export memory usage information. If **pid** is specified, the memory usage of the corresponding process is exported.| | --zip | Compresses the exported information to a specified folder.| -### Development Example +## Development Example HiDumper helps you export basic system information to locate and analyze faults. Complex parameters passed to sub-services and abilities must be enclosed in double quotation marks. @@ -118,7 +115,7 @@ The procedure is as follows: hidumper -s 3008 ``` -9. Run the **hidumper -e** command to obtain the crash information generated by the FaultLogger module. +9. Run the **hidumper -e** command to obtain the crash information generated by the FaultLoger module. ``` hidumper -e @@ -148,7 +145,7 @@ The procedure is as follows: hidumper -p 1024 ``` -14. Run the **hidumper --cpuusage [pid]** command to obtain the CPU usage information of the process whose PID has been specified. +14. Run the **hidumper --cpuusage [pid]** command to obtain the CPU usage information. If the PID of a process is specified, only the CPU usage of the process is returned. ``` hidumper --cpuusage @@ -161,7 +158,7 @@ The procedure is as follows: hidumper --cpufreq ``` -16. Run the **hidumper --mem [pid]** command to obtain all memory usage information of the process whose PID has been specified. +16. Run the **hidumper --mem [pid]** command to obtain all memory usage information. If the PID of a process is specified, only the memory usage of the process is returned. ``` hidumper --mem [pid] diff --git a/en/device-dev/subsystems/subsys-dfx-hitracechain.md b/en/device-dev/subsystems/subsys-dfx-hitracechain.md index e58467e1ca..f8a7c70451 100644 --- a/en/device-dev/subsystems/subsys-dfx-hitracechain.md +++ b/en/device-dev/subsystems/subsys-dfx-hitracechain.md @@ -146,9 +146,7 @@ Some built-in communication mechanisms (such as ZIDL) of OpenHarmony already sup The following figure shows the process of transferring **traceid** in synchronous call. The process of transferring **traceid** in asynchronous call is similar. Extended communication mechanisms can also follow this implementation. - **Figure 5** Call chain trace in synchronous communication - ![](figures/call-chain-trace-in-synchronous-communication.png "call-chain-trace-in-synchronous-communication") The process is as follows: diff --git a/en/device-dev/subsystems/subsys-dfx-hitracemeter.md b/en/device-dev/subsystems/subsys-dfx-hitracemeter.md index bb609b7369..12daba15d9 100644 --- a/en/device-dev/subsystems/subsys-dfx-hitracemeter.md +++ b/en/device-dev/subsystems/subsys-dfx-hitracemeter.md @@ -1,4 +1,4 @@ -# HiTraceMeter +# HiTraceMeter Development ## Introduction -- GitLab