diff --git a/LICENSE b/LICENSE new file mode 100755 index 0000000..4947287 --- /dev/null +++ b/LICENSE @@ -0,0 +1,177 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/OAT.xml b/OAT.xml new file mode 100755 index 0000000..d298c05 --- /dev/null +++ b/OAT.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + + diff --git a/README_zh.md b/README_zh.md new file mode 100755 index 0000000..64b2e18 --- /dev/null +++ b/README_zh.md @@ -0,0 +1,195 @@ +# 智能语音组件 + +## 概述 + +### 功能简介 + +智能语音组件包括智能语音服务框架和智能语音驱动,主要实现了语音注册及语音唤醒相关功能。 + +**图 1** 智能语音组件架构图 + +![image.png](figures/intelligent-voice-framework.png) + +智能语音服务框架支持如下功能: +系统事件监测:开机解锁、亮灭屏等系统事件监测 +并发策略:智能语音业务并发管理 +智能语音业务:语音注册、语音唤醒等智能语音业务处理 +声音触发器:DSP模型加载、DSP算法启停、DSP事件处理 + +智能语音驱动支持如下功能: +引擎算法:智能语音算法引擎以及事件上报 +设备驱动:DSP模型加载卸载、算法启停、事件上报以及硬件相关通路配置 + +### 基本概念 +- 语音注册:将用户说的唤醒词转换为声学模型以及声纹特征,以便后续的语音唤醒。 +- 语音唤醒:判断当前说话人是否为已注册的特定用户。 +- DSP:数字信号处理器(Digital Signal Processors),DSP芯片即指能够实现数字信号处理技术的芯片。 + +### 目录结构 + +仓目录结构如下: + +```shell +/foundation/ai/intelligent_voice_framework # 智能音频组件业务代码 +├── frameworks # 框架代码 +│ ├── native # 内部接口实现 +│ └── js # 外部接口实现 +├── interfaces # 接口代码 +│ ├── inner_api # 内部接口 +│ └── kits # 外部接口 +├── sa_profile # 服务配置文件 +├── services # 服务代码 +├── LICENSE # 证书文件 +├── tests # 开发者测试 +└── utils # 公共函数 +``` + +### 约束与限制 + +- 智能语音服务当前只支持一个唤醒词的注册以及唤醒。 + + +## 接口说明 +### 语音注册接口说明 + +|接口名称|接口描述| +|---|---| +|createEnrollIntelligentVoiceEngine(descriptor: EnrollIntelligentVoiceEngineDescriptor): EnrollIntelligentVoiceEngine|创建注册引擎。| +|init(config: EnrollEngineConfig): EnrollIntelligentVoiceEngineCallbackInfo|初始化注册引擎。| +|start(isLast: boolean): EnrollIntelligentVoiceEngineCallbackInfo|启动注册。| +|stop(): void|停止注册。| +|commit(): EnrollIntelligentVoiceEngineCallbackInfo|确认注册结果。| +|setWakeupHapInfo(info: WakeupHapInfo): void|设置唤醒应用信息。| +|setSensibility(sensibility: SensibilityType): void|设置灵敏度。| +|release(): void|释放注册引擎。| + +### 语音唤醒接口说明 + +|接口名称|接口描述| +|---|---| +|createWakeupIntelligentVoiceEngine(descriptor: WakeupIntelligentVoiceEngineDescriptor): WakeupIntelligentVoiceEngine|创建唤醒引擎。| +|setWakeupHapInfo(info: WakeupHapInfo): void|设置唤醒应用信息。| +|setSensibility(sensibility: SensibilityType): void|设置灵敏度。| +|on(type: 'wakeupIntelligentVoiceEvent', callback: Callback): void|订阅唤醒事件。| +|release(): void|释放唤醒引擎。| + + +## 开发实例 + +### 语音注册 + +语音注册流程是用户通过应用的注册界面主动发起的交互流程,主要流程如下: +1. 用户启动注册(创建注册引擎并初始化注册引擎)后,进入注册界面。 +2. 界面提示用户说出唤醒词,用户根据提示说出相应唤醒词(启动注册),界面会让用户再次重复说出唤醒词,直到最后一次。 +3. 注册完成(确认注册结果)后,注册流程全部完成。 +示例代码如下: + +```js +// 引入智能音频 +import intelligentVoice from '@ohos.ai.intelligentVoice'; + +// 获取智能音频管理服务 +var manager = intellVoice.getIntelligentVoiceManager(); +if (manager == null) { + console.error("Get IntelligentVoiceManager failed."); +} else { + console.info("Get IntelligentVoiceManager success."); + return; +} + +// 创建注册引擎 +var engine = null; +let engineDescriptor = { + wakeupPhrase: '', // 设置唤醒词 +} +await intellVoice.createEnrollIntelligentVoiceEngine(engineDescriptor).then((data) => { + engine = data; + console.info('Create EnrollIntelligentVoice Engine finish'); +}).catch((err) => { + console.error('Create EnrollIntelligentVoice Engine failed, err: ' + err.message); +}); +if (engine == null) { + console.error('Create EnrollIntelligentVoice Engine failed'); + return; +} + +// 初始化注册引擎 +let config = { + language: "zh", // 中文 + area: "CN", // 中国 +} +engine.init(config).then((data) => { + console.info('Init EnrollIntelligentVoice Engine finish'); +}).catch((err) => { + console.info('Init EnrollIntelligentVoice Engine failed, err: '+ err.message); +}); + +// 启动注册 +let isLast = true; // true: 最后一次启动,false: 非最后一次启动,实例为true +engine.start(isLast).then((data) => { + console.info('Start enrollment finish'); +}).catch((err) => { + console.info('Start enrollment failed, err: '+ err.message); +}); + +// 确认注册结果 +engine.commit().then((data) => { + console.info('Commit enroll result finish'); +}).catch((err) => { + console.info('Commit enroll result failed, err: '+ err.message); +}); + +// 下发语音唤醒应用信息 +let info = { + bundleName: "demo", // 应用的bundle name,demo只是个参考例子,具体填写由应用确定 + abilityName: "demo", // 应用的ability name,demo只是个参考例子,具体填写由应用确定 +} +engine.setWakeupHapInfo(info).then((data) => { + console.info('Set wakeup hap info finish'); +}).catch((err) => { + console.info('Set wakeup hap info failed, err: '+ err.message); +}); + +// 释放注册引擎 +engine.release().then((data) => { + console.info('Release EnrollIntelligentVoice engine success.'); +}).catch((err) => { + console.info('Release EnrollIntelligentVoice engine failed, err: '+ err.message); +}); +``` + +### 语音唤醒 + +语言唤醒由智能语音组件控制,上层应用只需要调用`createWakeupIntelligentVoiceEngine`获取唤醒引擎后注册唤醒事件回调即可。 + +```js +// 获取唤醒引擎 +var engine = null; +let engineDescriptor = { + needApAlgEngine: true, // 是否需要框架提供ap侧算法引擎 + wakeupPhrase: '', // 设置唤醒词 +} +await intellVoice.createWakeupIntelligentVoiceEngine(engineDescriptor).then((data) => { + engine = data; + console.info('Create WakeupIntelligentVoice Engine finish'); +}).catch((err) => { + console.error('Create WakeupIntelligentVoice Engine failed, err: ' + err.message); +}); +if (engine == null) { + console.error('Create WakeupIntelligentVoice Engine failed'); + return; +} + +// 注册事件回调 +engine.on('wakeupIntelligentVoiceEvent',(callback) => { + console.info('wakeupIntelligentVoiceEvent CallBackInfo:') + for (let prop in callback) { + console.info('wakeupIntelligentVoiceEvent prop: ' + prop); + console.info('wakeupIntelligentVoiceEvent value: ' + callback[prop]); + } +}); +``` + +## 相关仓 + +intelligent_voice_framework diff --git a/bundle.json b/bundle.json new file mode 100755 index 0000000..3963be1 --- /dev/null +++ b/bundle.json @@ -0,0 +1,57 @@ +{ + "name": "@ohos/intelligent_voice_framework", + "description": "intelligent_voice framework", + "version": "1.0", + "license": "Apache License 2.0", + "publishAs": "code-segment", + "segment": { + "destPath": "foundation/ai/intelligent_voice_framework" + }, + "component": { + "name": "intelligent_voice_framework", + "subsystem": "ai", + "syscap": [ + "SystemCapability.AI.IntelligentVoice.Core" + ], + "adapter_system_type": ["standard"], + "rom": "", + "ram": "", + "deps": { + "components": ["intelligent_voice_framework"], + "third_party": [] + }, + "features": [ + ], + "build": { + "sub_component": [ + "//foundation/ai/intelligent_voice_framework/services:intell_voice_server", + "//foundation/ai/intelligent_voice_framework/services:intell_voice_proxy", + "//foundation/ai/intelligent_voice_framework/services/etc:intell_voice_service.rc", + "//foundation/ai/intelligent_voice_framework/frameworks/js:intelligentvoice", + "//foundation/ai/intelligent_voice_framework/frameworks/js:intelligentvoice_js", + "//foundation/ai/intelligent_voice_framework/frameworks/native:intellvoice_native", + "//foundation/ai/intelligent_voice_framework/sa_profile:intell_voice_service_sa_profile" + ], + "inner_kits": [ + { + "type": "none", + "name": "//foundation/ai/intelligent_voice_framework/frameworks/js:intelligentvoice_js", + "header": { + "header_files": [ + "intell_voice_manager_napi.h", + "intell_voice_engine_napi.h", + "enroll_intell_voice_engine_napi.h" + ], + "header_base": [ + "//foundation/ai/intelligent_voice_framework/frameworks/js/napi/include" + ] + } + } + ], + "test": [ + "//foundation/ai/intelligent_voice_framework/tests:intell_voice_unit_test", + "//foundation/ai/intelligent_voice_framework/tests:intell_voice_fuzz_test" + ] + } + } +} diff --git a/figures/intelligent-voice-framework.png b/figures/intelligent-voice-framework.png new file mode 100755 index 0000000..d176720 Binary files /dev/null and b/figures/intelligent-voice-framework.png differ diff --git a/frameworks/js/BUILD.gn b/frameworks/js/BUILD.gn new file mode 100755 index 0000000..be6b399 --- /dev/null +++ b/frameworks/js/BUILD.gn @@ -0,0 +1,73 @@ +# Copyright (c) 2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("//build/ohos/ace/ace.gni") + +js_declaration("intelligentvoice_js") { + part_name = "intelligent_voice_framework" + sources = [ "//foundation/ai/intelligent_voice_framework/interfaces/kits/js/@ohos.ai.intelligentVoice.d.ts" ] +} + +ohos_copy("intelligentvoice_declaration") { + sources = [ "//foundation/ai/intelligent_voice_framework/interfaces/kits/js/@ohos.ai.intelligentVoice.d.ts" ] + outputs = [ target_out_dir + "/$target_name/" ] + module_source_dir = target_out_dir + "/$target_name" + module_install_name = "" +} + +ohos_shared_library("intelligentvoice") { + sources = [ + "napi/engine_event_callback_napi.cpp", + "napi/enroll_intell_voice_engine_callback_napi.cpp", + "napi/enroll_intell_voice_engine_napi.cpp", + "napi/intell_voice_manager_napi.cpp", + "napi/intell_voice_napi_queue.cpp", + "napi/intell_voice_napi_util.cpp", + "napi/wakeup_intell_voice_engine_napi.cpp", + ] + + include_dirs = [ + "//foundation/arkui/napi/interfaces/kits", + "//foundation/ai/intelligent_voice_framework/interfaces/inner_api/native", + "//foundation/ai/intelligent_voice_framework/services/intell_voice_engine", + "//foundation/ai/intelligent_voice_framework/services/intell_voice_engine/proxy", + "//foundation/ai/intelligent_voice_framework/utils", + "napi", + ] + + cflags_cc = [ + "-Wno-error=unused-parameter", + "-DHILOG_ENABLE", + "-DENABLE_DEBUG", + ] + + deps = [ + "//foundation/ai/intelligent_voice_framework/frameworks/native:intellvoice_native", + "//foundation/ai/intelligent_voice_framework/services:intell_voice_proxy", + "//foundation/arkui/napi:ace_napi", + ] + + external_deps = [ + "ability_base:want", + "c_utils:utils", + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + "safwk:system_ability_fwk", + "samgr:samgr_proxy", + ] + + relative_install_dir = "module/ai" + subsystem_name = "ai" + part_name = "intelligent_voice_framework" +} diff --git a/frameworks/js/napi/engine_event_callback_napi.cpp b/frameworks/js/napi/engine_event_callback_napi.cpp new file mode 100755 index 0000000..e0683b2 --- /dev/null +++ b/frameworks/js/napi/engine_event_callback_napi.cpp @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "engine_event_callback_napi.h" +#include +#include "intell_voice_log.h" + +using namespace std; +using namespace OHOS::IntellVoiceEngine; +#define LOG_TAG "EngineEventCallbackNapi" + +namespace OHOS { +namespace IntellVoiceNapi { +EngineEventCallbackNapi::EngineEventCallbackNapi(napi_env env, napi_value callback) +{ + INTELL_VOICE_LOG_INFO("enter"); + env_ = env; + if (env_ != nullptr) { + napi_get_uv_event_loop(env_, &loop_); + } + callbackRef_ = make_shared(env_, callback); +} + +EngineEventCallbackNapi::~EngineEventCallbackNapi() +{ + INTELL_VOICE_LOG_INFO("enter"); + callbackRef_ = nullptr; +} + +void EngineEventCallbackNapi::OnEvent(const IntellVoiceEngineCallBackEvent &event) +{ + INTELL_VOICE_LOG_INFO("enter"); + if (callbackRef_ == nullptr) { + INTELL_VOICE_LOG_ERROR("Failed to get engine event callback"); + return; + } + + EngineCallBackInfo cbInfo = {event.msgId, event.result, event.info}; + + INTELL_VOICE_LOG_INFO("OnEvent EngineCallBackInfo: msgId: %{public}d, errCode: %{public}d, context: %{public}s", + cbInfo.msgId, + cbInfo.errCode, + cbInfo.context.c_str()); + + return OnEventUvCallback(cbInfo); +} + +void EngineEventCallbackNapi::OnEventUvCallback(EngineCallBackInfo &cbInfo) +{ + CHECK_RETURN_VOID(loop_ != nullptr, "loop is nullptr"); + uv_work_t *work = new (nothrow) uv_work_t; + CHECK_RETURN_VOID(work != nullptr, "Create uv work failed, no memory"); + + work->data = new EngineEventUvCallback {env_, cbInfo, callbackRef_}; + + uv_queue_work( + loop_, + work, + [](uv_work_t *work) {}, + [](uv_work_t *work, int uvStatus) { + shared_ptr uvCallback( + static_cast(work->data), [work](EngineEventUvCallback *data) { + delete data; + delete work; + }); + CHECK_RETURN_VOID(uvCallback != nullptr, "uvCallback is nullptr"); + CHECK_RETURN_VOID(uvCallback->callback != nullptr, "uvCallback callback is nullptr"); + napi_env env = uvCallback->env_; + INTELL_VOICE_LOG_INFO("uv_queue_work start"); + + napi_value jsCallback = uvCallback->callback->GetRefValue(); + if (jsCallback == nullptr) { + INTELL_VOICE_LOG_ERROR("get reference value fail"); + return; + } + + const size_t argc = 1; + napi_value args[argc] = {nullptr}; + GetJsCallbackInfo(env, uvCallback->cbInfo, args[0]); + if (args[0] == nullptr) { + INTELL_VOICE_LOG_ERROR("failed to create engine event callback"); + return; + } + + napi_value result = nullptr; + napi_status status = napi_call_function(env, nullptr, jsCallback, argc, args, &result); + if (status != napi_ok) { + INTELL_VOICE_LOG_ERROR("failed to call engine event callback, error: %{public}d", status); + } + }); +} + +void GetJsCallbackInfo(const napi_env &env, const EngineCallBackInfo &callbackInfo, napi_value &jsObj) +{ + napi_status status = napi_create_object(env, &jsObj); + if (status != napi_ok || jsObj == nullptr) { + INTELL_VOICE_LOG_ERROR("failed to create js callbackInfo, error: %{public}d", status); + return; + } + + napi_set_named_property(env, jsObj, "msgId", SetValue(env, callbackInfo.msgId)); + napi_set_named_property(env, jsObj, "errCode", SetValue(env, callbackInfo.errCode)); + napi_set_named_property(env, jsObj, "context", SetValue(env, callbackInfo.context)); +} +} // namespace IntellVoiceNapi +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/js/napi/engine_event_callback_napi.h b/frameworks/js/napi/engine_event_callback_napi.h new file mode 100755 index 0000000..145662d --- /dev/null +++ b/frameworks/js/napi/engine_event_callback_napi.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ENGINE_EVENT_CALLBACK_H +#define ENGINE_EVENT_CALLBACK_H + +#include "napi/native_api.h" +#include "napi/native_node_api.h" +#include "intell_voice_napi_util.h" +#include "i_intell_voice_engine_callback.h" + +namespace OHOS { +namespace IntellVoiceNapi { +using OHOS::IntellVoiceEngine::IIntellVoiceEngineEventCallback; +using OHOS::IntellVoiceEngine::IntellVoiceEngineCallBackEvent; + +struct EngineCallBackInfo { + int32_t msgId; + int32_t errCode; + std::string context; +}; + +class EngineEventCallbackNapi : public IIntellVoiceEngineEventCallback { +public: + explicit EngineEventCallbackNapi(napi_env env, napi_value callback); + virtual ~EngineEventCallbackNapi(); + + void OnEvent(const IntellVoiceEngineCallBackEvent &event) override; + +private: + struct EngineEventUvCallback { + napi_env env_ = nullptr; + EngineCallBackInfo cbInfo; + std::shared_ptr callback; + }; + + void OnEventUvCallback(EngineCallBackInfo &cbInfo); + + napi_env env_ = nullptr; + uv_loop_s *loop_ = nullptr; + std::shared_ptr callbackRef_ = nullptr; +}; + +void GetJsCallbackInfo(const napi_env &env, const EngineCallBackInfo &callbackInfo, napi_value &jsObj); +} // namespace IntellVoiceNapi +} // namespace OHOS +#endif diff --git a/frameworks/js/napi/enroll_intell_voice_engine_callback_napi.cpp b/frameworks/js/napi/enroll_intell_voice_engine_callback_napi.cpp new file mode 100755 index 0000000..53c63f6 --- /dev/null +++ b/frameworks/js/napi/enroll_intell_voice_engine_callback_napi.cpp @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "enroll_intell_voice_engine_callback_napi.h" +#include "intell_voice_log.h" + +using namespace std; +using namespace OHOS::IntellVoiceEngine; +#define LOG_TAG "EnrollIntellVoiceEngineCallbackNapi" + +namespace OHOS { +namespace IntellVoiceNapi { +void EnrollIntellVoiceEngineCallBackInfo::GetCallBackInfoNapiValue(const napi_env &env, napi_value &result) +{ + napi_status status = napi_create_object(env, &result); + if (status != napi_ok || result == nullptr) { + INTELL_VOICE_LOG_ERROR("failed to create js callbackInfo, error: %{public}d", status); + return; + } + + napi_set_named_property(env, result, "eventId", SetValue(env, eventId)); + napi_set_named_property(env, result, "errCode", SetValue(env, errCode)); + napi_set_named_property(env, result, "context", SetValue(env, context)); +} + +EnrollIntellVoiceEngineCallbackNapi::EnrollIntellVoiceEngineCallbackNapi(const napi_env env) +{ + env_ = env; + contextMap_.clear(); +} + +EnrollIntellVoiceEngineCallbackNapi::~EnrollIntellVoiceEngineCallbackNapi() +{ + contextMap_.clear(); +} + +void EnrollIntellVoiceEngineCallbackNapi::QueueAsyncWork(EnrollAsyncContext *context) +{ + std::lock_guard lock(mutex_); + if (contextMap_.find(context->type) == contextMap_.end()) { + std::queue contextQue; + contextQue.push(context); + contextMap_[context->type] = contextQue; + } else { + contextMap_.at(context->type).push(context); + } +} + +void EnrollIntellVoiceEngineCallbackNapi::ClearAsyncWork(bool error, const std::string &msg) +{ + INTELL_VOICE_LOG_INFO("%{public}s", msg.c_str()); + std::lock_guard lock(mutex_); + for (auto it = contextMap_.begin(); it != contextMap_.end(); it++) { + auto &contextQue = it->second; + while (!contextQue.empty()) { + EnrollAsyncContext *context = contextQue.front(); + contextQue.pop(); + if (error) { + INTELL_VOICE_LOG_WARN("error occured"); + } + OnJsCallBack(context); + } + } + contextMap_.clear(); +} + +void EnrollIntellVoiceEngineCallbackNapi::OnEvent(const IntellVoiceEngineCallBackEvent &event) +{ + INTELL_VOICE_LOG_INFO("OnEvent: msgId: %{public}d, errCode: %{public}d, context: %{public}s", + event.msgId, + event.result, + event.info.c_str()); + EnrollAsyncWorkType asyncType = ASYNC_WORK_INVALID; + switch (event.msgId) { + case HDI::IntelligentVoice::Engine::V1_0::INTELL_VOICE_ENGINE_MSG_INIT_DONE: + asyncType = ASYNC_WORK_INIT; + break; + case HDI::IntelligentVoice::Engine::V1_0::INTELL_VOICE_ENGINE_MSG_ENROLL_COMPLETE: + asyncType = ASYNC_WORK_START; + break; + case HDI::IntelligentVoice::Engine::V1_0::INTELL_VOICE_ENGINE_MSG_COMMIT_ENROLL_COMPLETE: + asyncType = ASYNC_WORK_COMMIT; + break; + default: + break; + } + if (contextMap_.find(asyncType) == contextMap_.end() || contextMap_.at(asyncType).empty()) { + INTELL_VOICE_LOG_ERROR("callback is called, But context is empty"); + return; + } + + EnrollAsyncContext *context = contextMap_.at(asyncType).front(); + if (context == nullptr) { + INTELL_VOICE_LOG_ERROR("context is nullptr"); + return; + } + contextMap_.at(asyncType).pop(); + + context->callbackInfo = {event.msgId, event.result, event.info}; + OnJsCallBack(context); +} + +void EnrollIntellVoiceEngineCallbackNapi::UvWorkCallBack(uv_work_t *work, int status) +{ + INTELL_VOICE_LOG_INFO("enter"); + auto asyncContext = reinterpret_cast(work->data); + napi_value result = nullptr; + if (asyncContext != nullptr) { + napi_env env = asyncContext->env_; + asyncContext->callbackInfo.GetCallBackInfoNapiValue(env, result); + NapiAsync::CommonCallbackRoutine(asyncContext, result); + } + delete work; +} + +void EnrollIntellVoiceEngineCallbackNapi::OnJsCallBack(EnrollAsyncContext *context) +{ + INTELL_VOICE_LOG_INFO("enter"); + uv_loop_s *loop = nullptr; + napi_get_uv_event_loop(env_, &loop); + if (loop != nullptr) { + uv_work_t *work = new (std::nothrow) uv_work_t; + if (work != nullptr) { + work->data = reinterpret_cast(context); + int ret = uv_queue_work( + loop, work, [](uv_work_t *work) {}, UvWorkCallBack); + if (ret != 0) { + INTELL_VOICE_LOG_INFO("Failed to execute libuv work queue"); + delete context; + delete work; + } + } else { + delete context; + } + } else { + delete context; + } +} +} // namespace IntellVoiceNapi +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/js/napi/enroll_intell_voice_engine_callback_napi.h b/frameworks/js/napi/enroll_intell_voice_engine_callback_napi.h new file mode 100755 index 0000000..0ffd197 --- /dev/null +++ b/frameworks/js/napi/enroll_intell_voice_engine_callback_napi.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ENROLL_INTELL_VOICE_ENGINE_CALLBACK_NAPI_H +#define ENROLL_INTELL_VOICE_ENGINE_CALLBACK_NAPI_H + +#include +#include +#include +#include "napi/native_api.h" +#include "napi/native_node_api.h" +#include "intell_voice_napi_util.h" +#include "i_intell_voice_engine_callback.h" +#include "intell_voice_napi_queue.h" + +namespace OHOS { +namespace IntellVoiceNapi { +using OHOS::IntellVoiceEngine::IIntellVoiceEngineEventCallback; +using OHOS::IntellVoiceEngine::IntellVoiceEngineCallBackEvent; + +using ProcessWorkFunc = std::function; + +enum EnrollAsyncWorkType { + ASYNC_WORK_INIT = 0, + ASYNC_WORK_START, + ASYNC_WORK_COMMIT, + ASYNC_WORK_INVALID, +}; + +struct EnrollIntellVoiceEngineCallBackInfo { + int32_t eventId; + int32_t errCode; + std::string context; + + void GetCallBackInfoNapiValue(const napi_env &env, napi_value &result); +}; + +class EnrollAsyncContext : public AsyncContext { +public: + EnrollAsyncWorkType type = ASYNC_WORK_INVALID; + ProcessWorkFunc processWork = nullptr; + EnrollIntellVoiceEngineCallBackInfo callbackInfo; +}; + +class EnrollIntellVoiceEngineCallbackNapi : public IIntellVoiceEngineEventCallback { +public: + explicit EnrollIntellVoiceEngineCallbackNapi(const napi_env env); + virtual ~EnrollIntellVoiceEngineCallbackNapi(); + + void OnEvent(const IntellVoiceEngineCallBackEvent &event) override; + void QueueAsyncWork(EnrollAsyncContext *context); + void ClearAsyncWork(bool error, const std::string &msg); + +private: + void OnJsCallBack(EnrollAsyncContext *context); + static void UvWorkCallBack(uv_work_t *work, int status); + +private: + std::mutex mutex_; + napi_env env_ = nullptr; + + std::map> contextMap_; +}; +} // namespace IntellVoiceNapi +} // namespace OHOS +#endif diff --git a/frameworks/js/napi/enroll_intell_voice_engine_napi.cpp b/frameworks/js/napi/enroll_intell_voice_engine_napi.cpp new file mode 100755 index 0000000..dd19ee9 --- /dev/null +++ b/frameworks/js/napi/enroll_intell_voice_engine_napi.cpp @@ -0,0 +1,504 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "enroll_intell_voice_engine_napi.h" + +#include "iservice_registry.h" +#include "system_ability_definition.h" + +#include "intell_voice_napi_util.h" +#include "intell_voice_napi_queue.h" +#include "intell_voice_log.h" +#include "i_intell_voice_engine_callback.h" + +#define LOG_TAG "EnrollEngineNapi" + +using namespace OHOS::IntellVoice; +using namespace std; + +namespace OHOS { +namespace IntellVoiceNapi { +EnrollIntellVoiceEngineNapi::EnrollIntellVoiceEngineNapi() +{ + INTELL_VOICE_LOG_INFO("enter, %{public}p", this); +} + +EnrollIntellVoiceEngineNapi::~EnrollIntellVoiceEngineNapi() +{ + INTELL_VOICE_LOG_INFO("enter"); + if (wrapper_ != nullptr) { + napi_delete_reference(env_, wrapper_); + } +} + +napi_value EnrollIntellVoiceEngineNapi::New(napi_env env, napi_callback_info info) +{ + INTELL_VOICE_LOG_INFO("enter"); + size_t argc = 1; + napi_value args[1] = {nullptr}; + + napi_value jsThis = nullptr; + napi_value undefinedResult = nullptr; + napi_get_undefined(env, &undefinedResult); + + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &jsThis, nullptr)); + + unique_ptr engineNapi = make_unique(); + if (engineNapi == nullptr) { + INTELL_VOICE_LOG_ERROR("Failed to create EnrollIntellVoiceEngineNapi, No memory."); + return undefinedResult; + } + engineNapi->env_ = env; + + EnrollIntelligentVoiceEngineDescriptor descriptor = {}; + napi_value value = nullptr; + if (napi_get_named_property(env, args[0], "wakeupPhrase", &value) == napi_ok) { + GetValue(env, value, descriptor.wakeupPhrase); + } + INTELL_VOICE_LOG_INFO("EngineDescriptor wakeupPhrase: %{public}s", descriptor.wakeupPhrase.c_str()); + + engineNapi->engine_ = std::make_shared(descriptor); + if (engineNapi->engine_ == nullptr) { + INTELL_VOICE_LOG_ERROR("create intell voice engine faild."); + return undefinedResult; + } + engineNapi->callbackNapi_ = std::make_shared(env); + if (engineNapi->callbackNapi_ == nullptr) { + INTELL_VOICE_LOG_ERROR("create intell voice engine callback faild."); + return undefinedResult; + } + engineNapi->engine_->SetCallback(engineNapi->callbackNapi_); + + auto finalize = [](napi_env env, void *data, void *hint) { + INTELL_VOICE_LOG_INFO("EnrollIntellVoiceEngineNapi finalize callback"); + if (data != nullptr) { + auto obj = static_cast(data); + delete obj; + } + }; + + NAPI_CALL( + env, napi_wrap(env, jsThis, static_cast(engineNapi.get()), finalize, nullptr, &(engineNapi->wrapper_))); + engineNapi.release(); + return jsThis; +} + +napi_value EnrollIntellVoiceEngineNapi::Constructor(napi_env env) +{ + INTELL_VOICE_LOG_INFO("enter"); + napi_status status; + napi_value constructor; + napi_get_undefined(env, &constructor); + + napi_property_descriptor properties[] = { + DECLARE_NAPI_FUNCTION("getSupportedRegions", GetSupportedRegions), + DECLARE_NAPI_FUNCTION("init", Init), + DECLARE_NAPI_FUNCTION("start", Start), + DECLARE_NAPI_FUNCTION("stop", Stop), + DECLARE_NAPI_FUNCTION("setSensibility", SetSensibility), + DECLARE_NAPI_FUNCTION("setWakeupHapInfo", SetWakeupHapInfo), + DECLARE_NAPI_FUNCTION("setParameter", SetParameter), + DECLARE_NAPI_FUNCTION("getParameter", GetParameter), + DECLARE_NAPI_FUNCTION("release", Release), + DECLARE_NAPI_FUNCTION("commit", Commit), + }; + + status = napi_define_class(env, + ENROLL_ENGINE_NAPI_CLASS_NAME, + NAPI_AUTO_LENGTH, + New, + nullptr, + sizeof(properties) / sizeof(properties[0]), + properties, + &constructor); + + return constructor; +} + +napi_value EnrollIntellVoiceEngineNapi::GetSupportedRegions(napi_env env, napi_callback_info info) +{ + INTELL_VOICE_LOG_INFO("enter"); + size_t cbIndex = 0; + shared_ptr context = make_shared(); + if (context == nullptr) { + INTELL_VOICE_LOG_ERROR("create AsyncContext faild, No memory"); + return nullptr; + } + + context->GetCbInfo(env, info, cbIndex, nullptr); + + AsyncExecute execute = [](napi_env env, void *data) { + auto asyncContext = static_cast(data); + asyncContext->status_ = napi_ok; + }; + + AsyncComplete complete = [](AsyncContext *context, napi_value &result) { + INTELL_VOICE_LOG_INFO("get supported regions complete"); + napi_create_array(context->env_, &result); + napi_set_element(context->env_, result, 0, SetValue(context->env_, "CN")); + }; + + return NapiAsync::AsyncWork(context, "GetSupportedRegions", execute, complete); +} + +napi_value EnrollIntellVoiceEngineNapi::Init(napi_env env, napi_callback_info info) +{ + INTELL_VOICE_LOG_INFO("enter"); + size_t cbIndex = 1; + auto context = make_shared(); + if (context == nullptr) { + INTELL_VOICE_LOG_ERROR("create InitContext faild, No memory"); + return nullptr; + } + + CbInfoParser parser = [env, context](size_t argc, napi_value *argv) { + napi_value temp = nullptr; + if (napi_get_named_property(env, argv[0], "language", &temp) == napi_ok) { + GetValue(env, temp, + reinterpret_cast(context->engineNapi_)->config_.language); + } + if (napi_get_named_property(env, argv[0], "region", &temp) == napi_ok) { + GetValue(env, temp, + reinterpret_cast(context->engineNapi_)->config_.region); + } + }; + + context->GetCbInfo(env, info, cbIndex, parser); + + context->type = ASYNC_WORK_INIT; + context->callbackInfo.eventId = INTELLIGENT_VOICE_EVENT_ENROLL_INIT_DONE; + context->callbackInfo.errCode = INTELLIGENT_VOICE_INIT_FAILED; + context->processWork = [&](AsyncContext *asyncContext) { + EnrollIntellVoiceEngineNapi *engineNapi = reinterpret_cast( + asyncContext->engineNapi_); + auto engine = engineNapi->engine_; + if (engine == nullptr) { + INTELL_VOICE_LOG_ERROR("get engine instance faild"); + return -1; + } + return engine->Init(engineNapi->config_); + }; + + AsyncExecute execute = [](napi_env env, void *data) {}; + + return NapiAsync::AsyncWork(context, "Init", execute, CompleteCallback); +} + +napi_value EnrollIntellVoiceEngineNapi::Start(napi_env env, napi_callback_info info) +{ + INTELL_VOICE_LOG_INFO("enter"); + size_t cbIndex = 1; + auto context = make_shared(); + if (context == nullptr) { + INTELL_VOICE_LOG_ERROR("create StartContext faild, No memory"); + return nullptr; + } + + CbInfoParser parser = [env, context](size_t argc, napi_value *argv) { + context->status_ = GetValue(env, argv[0], + reinterpret_cast(context->engineNapi_)->isLast_); + CHECK_STATUS_RETURN_VOID(context, "Failed to get isLast"); + }; + + context->GetCbInfo(env, info, cbIndex, parser); + + context->type = ASYNC_WORK_START; + context->callbackInfo.eventId = INTELLIGENT_VOICE_EVENT_ENROLL_COMPLETE; + context->callbackInfo.errCode = INTELLIGENT_VOICE_ENROLL_FAILED; + context->processWork = [&](AsyncContext *asyncContext) { + EnrollIntellVoiceEngineNapi *engineNapi = reinterpret_cast( + asyncContext->engineNapi_); + auto engine = engineNapi->engine_; + if (engine == nullptr) { + INTELL_VOICE_LOG_ERROR("get engine instance faild"); + return -1; + } + + return engine->Start(engineNapi->isLast_); + }; + + AsyncExecute execute = [](napi_env env, void *data) {}; + + return NapiAsync::AsyncWork(context, "Start", execute, CompleteCallback); +} + +napi_value EnrollIntellVoiceEngineNapi::Stop(napi_env env, napi_callback_info info) +{ + INTELL_VOICE_LOG_INFO("enter"); + size_t cbIndex = 0; + auto context = make_shared(); + if (context == nullptr) { + INTELL_VOICE_LOG_ERROR("create AsyncContext faild, No memory"); + return nullptr; + } + + context->GetCbInfo(env, info, cbIndex, nullptr); + + auto cb = reinterpret_cast(context->engineNapi_)->callbackNapi_; + if (cb != nullptr) { + cb->ClearAsyncWork(false, "the requests was aborted because user called stop"); + } + + AsyncExecute execute = [](napi_env env, void *data) { + auto asyncContext = static_cast(data); + auto engine = reinterpret_cast(asyncContext->engineNapi_)->engine_; + if (engine == nullptr) { + INTELL_VOICE_LOG_ERROR("get engine instance faild"); + return; + } + asyncContext->result_ = engine->Stop(); + asyncContext->status_ = napi_ok; + }; + + return NapiAsync::AsyncWork(context, "Stop", execute); +} + +napi_value EnrollIntellVoiceEngineNapi::SetParameter(napi_env env, napi_callback_info info) +{ + INTELL_VOICE_LOG_INFO("enter"); + size_t cbIndex = 2; + class SetParameterContext : public AsyncContext { + public: + string key; + string value; + }; + auto context = make_shared(); + if (context == nullptr) { + INTELL_VOICE_LOG_ERROR("create SetParameterContext faild, No memory"); + return nullptr; + } + + CbInfoParser parser = [env, context](size_t argc, napi_value *argv) { + context->status_ = GetValue(env, argv[0], context->key); + CHECK_STATUS_RETURN_VOID(context, "Failed to get key"); + context->status_ = GetValue(env, argv[1], context->value); + CHECK_STATUS_RETURN_VOID(context, "Failed to get value"); + }; + + context->GetCbInfo(env, info, cbIndex, parser); + + AsyncExecute execute = [](napi_env env, void *data) { + auto asyncContext = static_cast(data); + auto engine = reinterpret_cast(asyncContext->engineNapi_)->engine_; + if (engine == nullptr) { + INTELL_VOICE_LOG_ERROR("get engine instance faild"); + return; + } + asyncContext->result_ = engine->SetParameter(asyncContext->key, asyncContext->value); + asyncContext->status_ = napi_ok; + }; + + return NapiAsync::AsyncWork(context, "SetParameter", execute); +} + +napi_value EnrollIntellVoiceEngineNapi::GetParameter(napi_env env, napi_callback_info info) +{ + INTELL_VOICE_LOG_INFO("enter"); + size_t cbIndex = 1; + shared_ptr context = make_shared(); + if (context == nullptr) { + INTELL_VOICE_LOG_ERROR("create AsyncContext faild, No memory"); + return nullptr; + } + + context->GetCbInfo(env, info, cbIndex, nullptr); + + AsyncExecute execute = [](napi_env env, void *data) { + auto asyncContext = static_cast(data); + asyncContext->status_ = napi_ok; + }; + + AsyncComplete complete = [](AsyncContext *context, napi_value &result) { + INTELL_VOICE_LOG_INFO("get parameter complete"); + result = SetValue(context->env_, "value"); + }; + return NapiAsync::AsyncWork(context, "GetParameter", execute, complete); +} + +napi_value EnrollIntellVoiceEngineNapi::SetSensibility(napi_env env, napi_callback_info info) +{ + INTELL_VOICE_LOG_INFO("enter"); + size_t cbIndex = 1; + class SetSensibilityContext : public AsyncContext { + public: + int32_t sensibility; + }; + auto context = make_shared(); + if (context == nullptr) { + INTELL_VOICE_LOG_ERROR("create SetSensibilityContext faild, No memory"); + return nullptr; + } + + CbInfoParser parser = [env, context](size_t argc, napi_value *argv) { + context->status_ = GetValue(env, argv[0], context->sensibility); + CHECK_STATUS_RETURN_VOID(context, "Failed to get sensibility"); + }; + + context->GetCbInfo(env, info, cbIndex, parser); + + AsyncExecute execute = [](napi_env env, void *data) { + auto asyncContext = static_cast(data); + auto engine = reinterpret_cast(asyncContext->engineNapi_)->engine_; + if (engine == nullptr) { + INTELL_VOICE_LOG_ERROR("get engine instance faild"); + return; + } + asyncContext->result_ = engine->SetSensibility(asyncContext->sensibility); + asyncContext->status_ = napi_ok; + }; + + return NapiAsync::AsyncWork(context, "SetSensibility", execute); +} + +napi_value EnrollIntellVoiceEngineNapi::SetWakeupHapInfo(napi_env env, napi_callback_info info) +{ + INTELL_VOICE_LOG_INFO("enter"); + size_t cbIndex = 1; + class SetWakeupHapContext : public AsyncContext { + public: + WakeupHapInfo hapInfo; + }; + auto context = make_shared(); + if (context == nullptr) { + INTELL_VOICE_LOG_ERROR("create SetWakeupHapContext faild, No memory"); + return nullptr; + } + + CbInfoParser parser = [env, context](size_t argc, napi_value *argv) { + napi_value temp = nullptr; + if (napi_get_named_property(env, argv[0], "bundleName", &temp) == napi_ok) { + GetValue(env, temp, context->hapInfo.bundleName); + } + if (napi_get_named_property(env, argv[0], "abilityName", &temp) == napi_ok) { + GetValue(env, temp, context->hapInfo.abilityName); + } + }; + + context->GetCbInfo(env, info, cbIndex, parser); + + AsyncExecute execute = [](napi_env env, void *data) { + auto asyncContext = static_cast(data); + auto engine = reinterpret_cast(asyncContext->engineNapi_)->engine_; + if (engine == nullptr) { + INTELL_VOICE_LOG_ERROR("get engine instance faild"); + return; + } + asyncContext->result_ = engine->SetWakeupHapInfo(asyncContext->hapInfo); + asyncContext->status_ = napi_ok; + }; + + return NapiAsync::AsyncWork(context, "SetWakeupHapInfo", execute); +} + +napi_value EnrollIntellVoiceEngineNapi::Commit(napi_env env, napi_callback_info info) +{ + INTELL_VOICE_LOG_INFO("enter"); + size_t cbIndex = 0; + auto context = make_shared(); + if (context == nullptr) { + INTELL_VOICE_LOG_ERROR("create IntellVoiceContext faild, No memory"); + return nullptr; + } + + context->GetCbInfo(env, info, cbIndex, nullptr); + + context->type = ASYNC_WORK_COMMIT; + context->callbackInfo.eventId = INTELLIGENT_VOICE_EVENT_COMMIT_ENROLL_COMPLETE; + context->callbackInfo.errCode = INTELLIGENT_VOICE_COMMIT_ENROLL_FAILED; + context->processWork = [](AsyncContext *asyncContext) { + auto engine = reinterpret_cast(asyncContext->engineNapi_)->engine_; + if (engine == nullptr) { + INTELL_VOICE_LOG_ERROR("get engine instance faild"); + return -1; + } + + return engine->Commit(); + }; + + AsyncExecute execute = [](napi_env env, void *data) {}; + + return NapiAsync::AsyncWork(context, "Commit", execute, CompleteCallback); +} + +napi_value EnrollIntellVoiceEngineNapi::Release(napi_env env, napi_callback_info info) +{ + INTELL_VOICE_LOG_INFO("enter"); + size_t cbIndex = 0; + shared_ptr context = make_shared(); + if (context == nullptr) { + INTELL_VOICE_LOG_ERROR("create AsyncContext faild, No memory"); + return nullptr; + } + + context->GetCbInfo(env, info, cbIndex, nullptr); + + AsyncExecute execute = [](napi_env env, void *data) { + auto asyncContext = static_cast(data); + auto cb = reinterpret_cast(asyncContext->engineNapi_)->callbackNapi_; + if (cb != nullptr) { + cb->ClearAsyncWork(false, "the requests was aborted because user called release"); + } + auto engine = reinterpret_cast(asyncContext->engineNapi_)->engine_; + if (engine == nullptr) { + INTELL_VOICE_LOG_ERROR("get engine instance faild"); + return; + } + asyncContext->result_ = engine->Release(); + asyncContext->status_ = napi_ok; + reinterpret_cast(asyncContext->engineNapi_)->engine_ = nullptr; + reinterpret_cast(asyncContext->engineNapi_)->callbackNapi_ = nullptr; + }; + + AsyncComplete complete = [](AsyncContext *context, napi_value &result) { + INTELL_VOICE_LOG_INFO("release engine complete"); + }; + return NapiAsync::AsyncWork(context, "Release", execute, complete); +} + +void EnrollIntellVoiceEngineNapi::CompleteCallback(napi_env env, napi_status status, void *data) +{ + INTELL_VOICE_LOG_INFO("enter"); + CHECK_RETURN_VOID(data != nullptr, "async complete callback data is null"); + napi_value result = nullptr; + napi_get_undefined(env, &result); + + auto asyncContext = static_cast(data); + if ((status != napi_ok) && (asyncContext->status_ == napi_ok)) { + asyncContext->status_ = status; + NapiAsync::CommonCallbackRoutine(asyncContext, result); + return; + } + + if (asyncContext->processWork == nullptr) { + INTELL_VOICE_LOG_ERROR("process work is nullptr"); + NapiAsync::CommonCallbackRoutine(asyncContext, result); + return; + } + + auto cb = reinterpret_cast(asyncContext->engineNapi_)->callbackNapi_; + if (cb == nullptr) { + INTELL_VOICE_LOG_ERROR("get callback napi faild"); + NapiAsync::CommonCallbackRoutine(asyncContext, result); + return; + } + + cb->QueueAsyncWork(asyncContext); + if (asyncContext->processWork(asyncContext) != 0) { + INTELL_VOICE_LOG_ERROR("process work failed"); + cb->ClearAsyncWork(true, "the request was aborted because intelligent voice processWork error"); + } +} +} // namespace IntellVoiceNapi +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/js/napi/enroll_intell_voice_engine_napi.h b/frameworks/js/napi/enroll_intell_voice_engine_napi.h new file mode 100755 index 0000000..fe754c7 --- /dev/null +++ b/frameworks/js/napi/enroll_intell_voice_engine_napi.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ENROLL_INTELL_VOICE_ENGINE_NAPI_H +#define ENROLL_INTELL_VOICE_ENGINE_NAPI_H + +#include +#include "napi/native_api.h" +#include "napi/native_node_api.h" +#include "enroll_intell_voice_engine.h" +#include "enroll_intell_voice_engine_callback_napi.h" + +#define ENROLL_ENGINE_NAPI_CLASS_NAME "EnrollIntelligentVoiceEngine" + +namespace OHOS { +namespace IntellVoiceNapi { +using OHOS::IntellVoice::EnrollIntellVoiceEngine; +using OHOS::IntellVoice::EngineConfig; + +class EnrollIntellVoiceEngineNapi { +public: + EnrollIntellVoiceEngineNapi(); + ~EnrollIntellVoiceEngineNapi(); + + static napi_value Constructor(napi_env env); + +private: + static napi_value New(napi_env env, napi_callback_info info); + + static napi_value GetSupportedRegions(napi_env env, napi_callback_info info); + static napi_value Init(napi_env env, napi_callback_info info); + static napi_value Start(napi_env env, napi_callback_info info); + static napi_value Stop(napi_env env, napi_callback_info info); + static napi_value Commit(napi_env env, napi_callback_info info); + static napi_value SetSensibility(napi_env env, napi_callback_info info); + static napi_value SetWakeupHapInfo(napi_env env, napi_callback_info info); + static napi_value SetParameter(napi_env env, napi_callback_info info); + static napi_value GetParameter(napi_env env, napi_callback_info info); + static napi_value Release(napi_env env, napi_callback_info info); + + static void CompleteCallback(napi_env env, napi_status status, void *data); + + std::shared_ptr engine_ = nullptr; + std::shared_ptr callbackNapi_ = nullptr; + EngineConfig config_; + bool isLast_ = false; + +private: + napi_env env_ = nullptr; + napi_ref wrapper_ = nullptr; +}; +} // namespace IntellVoiceNapi +} // namespace OHOS + +#endif diff --git a/frameworks/js/napi/intell_voice_manager_napi.cpp b/frameworks/js/napi/intell_voice_manager_napi.cpp new file mode 100755 index 0000000..a7dabe9 --- /dev/null +++ b/frameworks/js/napi/intell_voice_manager_napi.cpp @@ -0,0 +1,420 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "intell_voice_manager_napi.h" +#include "intell_voice_log.h" +#include "intell_voice_napi_queue.h" +#include "intell_voice_napi_util.h" +#include "enroll_intell_voice_engine_napi.h" +#include "wakeup_intell_voice_engine_napi.h" +#include "intell_voice_info.h" + +#define LOG_TAG "IntellVoiceManagerNapi" + +using namespace std; +using namespace OHOS::IntellVoice; + +namespace OHOS { +namespace IntellVoiceNapi { +static const std::string INTELLIGENT_VOICE_MANAGER_NAPI_CLASS_NAME = "IntelligentVoiceManager"; + +static __thread napi_ref g_managerConstructor = nullptr; +napi_ref IntellVoiceManagerNapi::serviceChangeTypeRef_ = nullptr; +napi_ref IntellVoiceManagerNapi::engineTypeRef_ = nullptr; +napi_ref IntellVoiceManagerNapi::sensibilityTypeRef_ = nullptr; +napi_ref IntellVoiceManagerNapi::enrollEventTypeRef_ = nullptr; +napi_ref IntellVoiceManagerNapi::wakeupEventTypeRef_ = nullptr; +napi_ref IntellVoiceManagerNapi::errorCodeRef_ = nullptr; + +static const std::map SERVICE_CHANGE_TYPE_MAP = { + {"SERVICE_UNAVAILABLE", SERVICE_UNAVAILABLE}, +}; + +static const std::map ENGINE_TYPE_MAP = { + {"ENROLL_ENGINE_TYPE", ENROLL_ENGINE_TYPE}, + {"WAKEUP_ENGINE_TYPE", WAKEUP_ENGINE_TYPE}, + {"UPDATE_ENGINE_TYPE", UPDATE_ENGINE_TYPE}, +}; + +static const std::map SENSIBILITY_TYPE_MAP = { + {"LOW_SENSIBILITY", LOW_SENSIBILITY}, + {"MIDDLE_SENSIBILITY", MIDDLE_SENSIBILITY}, + {"HIGH_SENSIBILITY", HIGH_SENSIBILITY}, +}; + +static const std::map ENROLL_EVENT_TYPE_MAP = { + {"INTELLIGENT_VOICE_EVENT_ENROLL_NONE", INTELLIGENT_VOICE_EVENT_ENROLL_NONE}, + {"INTELLIGENT_VOICE_EVENT_ENROLL_INIT_DONE", INTELLIGENT_VOICE_EVENT_ENROLL_INIT_DONE}, + {"INTELLIGENT_VOICE_EVENT_ENROLL_COMPLETE", INTELLIGENT_VOICE_EVENT_ENROLL_COMPLETE}, + {"INTELLIGENT_VOICE_EVENT_COMMIT_ENROLL_COMPLETE", INTELLIGENT_VOICE_EVENT_COMMIT_ENROLL_COMPLETE}, +}; + +static const std::map WAKEUP_EVENT_TYPE_MAP = { + {"INTELLIGENT_VOICE_EVENT_WAKEUP_NONE", INTELLIGENT_VOICE_EVENT_WAKEUP_NONE}, + {"INTELLIGENT_VOICE_EVENT_RECOGNIZE_COMPLETE", INTELLIGENT_VOICE_EVENT_RECOGNIZE_COMPLETE}, +}; + +static const std::map ERROR_CODE_MAP = { + {"INTELLIGENT_VOICE_SUCCESS", INTELLIGENT_VOICE_SUCCESS}, + {"INTELLIGENT_VOICE_NO_MEMORY", INTELLIGENT_VOICE_NO_MEMORY}, + {"INTELLIGENT_VOICE_INVALID_PARAM", INTELLIGENT_VOICE_INVALID_PARAM}, + {"INTELLIGENT_VOICE_INIT_FAILED", INTELLIGENT_VOICE_INIT_FAILED}, + {"INTELLIGENT_VOICE_ENROLL_FAILED", INTELLIGENT_VOICE_ENROLL_FAILED}, + {"INTELLIGENT_VOICE_COMMIT_ENROLL_FAILED", INTELLIGENT_VOICE_COMMIT_ENROLL_FAILED}, + {"INTELLIGENT_VOICE_RECOGNIZE_FAILED", INTELLIGENT_VOICE_RECOGNIZE_FAILED}, +}; + +IntellVoiceManagerNapi::IntellVoiceManagerNapi() +{ + INTELL_VOICE_LOG_INFO("enter"); +} + +IntellVoiceManagerNapi::~IntellVoiceManagerNapi() +{ + INTELL_VOICE_LOG_INFO("enter"); + if (wrapper_ != nullptr) { + napi_delete_reference(env_, wrapper_); + } +} + +void IntellVoiceManagerNapi::Destructor(napi_env env, void *nativeObject, void *finalize_hint) +{ + INTELL_VOICE_LOG_INFO("enter"); + if (nativeObject != nullptr) { + auto obj = static_cast(nativeObject); + delete obj; + } +} + +napi_value IntellVoiceManagerNapi::Constructor(napi_env env, napi_callback_info info) +{ + INTELL_VOICE_LOG_INFO("enter"); + napi_status status; + size_t argCount = 0; + napi_value jsThis = nullptr; + napi_value undefinedResult = nullptr; + napi_get_undefined(env, &undefinedResult); + + status = napi_get_cb_info(env, info, &argCount, nullptr, &jsThis, nullptr); + if (status != napi_ok) { + INTELL_VOICE_LOG_ERROR("invalid number of arguments"); + return undefinedResult; + } + + unique_ptr managerNapi = make_unique(); + if (managerNapi == nullptr) { + INTELL_VOICE_LOG_ERROR("no memory."); + return undefinedResult; + } + managerNapi->env_ = env; + managerNapi->manager_ = IntellVoiceManager::GetInstance(); + if (managerNapi->manager_ == nullptr) { + INTELL_VOICE_LOG_ERROR("create native manager faild."); + return undefinedResult; + } + + status = napi_wrap(env, + jsThis, + static_cast(managerNapi.get()), + IntellVoiceManagerNapi::Destructor, + nullptr, + &(managerNapi->wrapper_)); + if (status == napi_ok) { + managerNapi.release(); + return jsThis; + } + + INTELL_VOICE_LOG_ERROR("failed to construct intell voice manager napi"); + return undefinedResult; +} + +napi_value IntellVoiceManagerNapi::Export(napi_env env, napi_value exports) +{ + INTELL_VOICE_LOG_INFO("enter"); + napi_status status; + napi_value constructor; + napi_value result = nullptr; + const int32_t refCount = 1; + napi_get_undefined(env, &result); + + napi_property_descriptor properties[] = { + DECLARE_NAPI_FUNCTION("getCapabilityInfo", GetCapabilityInfo), + DECLARE_NAPI_FUNCTION("on", On), + DECLARE_NAPI_FUNCTION("off", Off), + }; + + napi_property_descriptor staticProperties[] = { + DECLARE_NAPI_STATIC_FUNCTION("getIntelligentVoiceManager", GetIntelligentVoiceManager), + DECLARE_NAPI_PROPERTY("ServiceChangeType", CreatePropertyBase(env, SERVICE_CHANGE_TYPE_MAP, + serviceChangeTypeRef_)), + DECLARE_NAPI_PROPERTY("IntelligentVoiceEngineType", CreatePropertyBase(env, ENGINE_TYPE_MAP, + engineTypeRef_)), + DECLARE_NAPI_PROPERTY("SensibilityType", CreatePropertyBase(env, SENSIBILITY_TYPE_MAP, + sensibilityTypeRef_)), + DECLARE_NAPI_PROPERTY("EnrollIntelligentVoiceEventType", CreatePropertyBase(env, ENROLL_EVENT_TYPE_MAP, + enrollEventTypeRef_)), + DECLARE_NAPI_PROPERTY("WakeupIntelligentVoiceEventType", CreatePropertyBase(env, WAKEUP_EVENT_TYPE_MAP, + wakeupEventTypeRef_)), + DECLARE_NAPI_PROPERTY("IntelligentVoiceErrorCode", CreatePropertyBase(env, ERROR_CODE_MAP, errorCodeRef_)), + }; + + status = napi_define_class(env, + INTELLIGENT_VOICE_MANAGER_NAPI_CLASS_NAME.c_str(), + NAPI_AUTO_LENGTH, + Constructor, + nullptr, + sizeof(properties) / sizeof(properties[0]), + properties, + &constructor); + if (status != napi_ok) { + return result; + } + + status = napi_create_reference(env, constructor, refCount, &g_managerConstructor); + if (status == napi_ok) { + status = napi_set_named_property(env, exports, INTELLIGENT_VOICE_MANAGER_NAPI_CLASS_NAME.c_str(), constructor); + if (status == napi_ok) { + status = napi_define_properties( + env, exports, sizeof(staticProperties) / sizeof(staticProperties[0]), staticProperties); + if (status == napi_ok) { + return exports; + } + } + } + + INTELL_VOICE_LOG_ERROR("failed to export intelligent voice manager napi"); + return result; +} + +napi_value IntellVoiceManagerNapi::GetCapabilityInfo(napi_env env, napi_callback_info info) +{ + INTELL_VOICE_LOG_INFO("enter"); + napi_value result = nullptr; + napi_create_array(env, &result); + napi_set_element(env, result, 0, SetValue(env, ENROLL_ENGINE_TYPE)); + napi_set_element(env, result, 1, SetValue(env, WAKEUP_ENGINE_TYPE)); + return result; +} + +napi_value IntellVoiceManagerNapi::On(napi_env env, napi_callback_info info) +{ + INTELL_VOICE_LOG_INFO("enter"); + return nullptr; +} + +napi_value IntellVoiceManagerNapi::Off(napi_env env, napi_callback_info info) +{ + INTELL_VOICE_LOG_INFO("enter"); + return nullptr; +} + +napi_value IntellVoiceManagerNapi::GetIntelligentVoiceManager(napi_env env, napi_callback_info info) +{ + INTELL_VOICE_LOG_INFO("enter"); + + napi_status status; + size_t argCount = 0; + + status = napi_get_cb_info(env, info, &argCount, nullptr, nullptr, nullptr); + if (status != napi_ok || argCount != 0) { + INTELL_VOICE_LOG_ERROR("Invalid arguments"); + return nullptr; + } + + return IntellVoiceManagerNapi::GetIntelligentVoiceManagerWrapper(env); +} + +napi_value IntellVoiceManagerNapi::GetIntelligentVoiceManagerWrapper(napi_env env) +{ + napi_status status; + napi_value result = nullptr; + napi_value constructor; + + status = napi_get_reference_value(env, g_managerConstructor, &constructor); + if (status == napi_ok) { + status = napi_new_instance(env, constructor, 0, nullptr, &result); + if (status == napi_ok) { + return result; + } + } + INTELL_VOICE_LOG_ERROR("failed to get intell voice manager wrapper"); + napi_get_undefined(env, &result); + + return result; +} + +napi_value IntellVoiceManagerNapi::CreateEnrollIntelligentVoiceEngine(napi_env env, napi_callback_info info) +{ + INTELL_VOICE_LOG_INFO("enter"); + size_t cbIndex = 1; + class CreateContext : public AsyncContext { + public: + napi_value object = nullptr; + napi_ref ref = nullptr; + }; + auto context = make_shared(); + if (context == nullptr) { + INTELL_VOICE_LOG_ERROR("create CreateContext faild, No memory"); + return nullptr; + } + + CbInfoParser parser = [env, context](size_t argc, napi_value *argv) { + context->status_ = + napi_new_instance(env, EnrollIntellVoiceEngineNapi::Constructor(env), argc, argv, &(context->object)); + CHECK_STATUS_RETURN_VOID(context, "new napi instance failed"); + context->status_ = napi_create_reference(env, context->object, 1, &(context->ref)); + CHECK_STATUS_RETURN_VOID(context, "create ref failed"); + }; + context->GetCbInfo(env, info, cbIndex, parser); + + AsyncExecute execute = [](napi_env env, void *data) { + auto asyncContext = static_cast(data); + asyncContext->status_ = napi_ok; + }; + + AsyncComplete complete = [](AsyncContext *context, napi_value &result) { + auto createContext = static_cast(context); + napi_get_reference_value(createContext->env_, createContext->ref, &result); + }; + + return NapiAsync::AsyncWork(context, "CreateEnrollIntelligentVoiceEngine", execute, complete); +} + +napi_value IntellVoiceManagerNapi::CreateWakeupIntelligentVoiceEngine(napi_env env, napi_callback_info info) +{ + INTELL_VOICE_LOG_INFO("enter"); + size_t cbIndex = 1; + class CreateContext : public AsyncContext { + public: + napi_value object = nullptr; + napi_ref ref = nullptr; + }; + auto context = make_shared(); + if (context == nullptr) { + INTELL_VOICE_LOG_ERROR("create CreateContext faild, No memory"); + return nullptr; + } + + CbInfoParser parser = [env, context](size_t argc, napi_value *argv) { + context->status_ = + napi_new_instance(env, WakeupIntellVoiceEngineNapi::Constructor(env), argc, argv, &(context->object)); + CHECK_STATUS_RETURN_VOID(context, "new napi instance failed"); + context->status_ = napi_create_reference(env, context->object, 1, &(context->ref)); + CHECK_STATUS_RETURN_VOID(context, "create ref failed"); + }; + context->GetCbInfo(env, info, cbIndex, parser); + + AsyncExecute execute = [](napi_env env, void *data) { + auto asyncContext = static_cast(data); + asyncContext->status_ = napi_ok; + }; + + AsyncComplete complete = [](AsyncContext *context, napi_value &result) { + auto createContext = static_cast(context); + napi_get_reference_value(createContext->env_, createContext->ref, &result); + }; + + return NapiAsync::AsyncWork(context, "CreateWakeupIntelligentVoiceEngine", execute, complete); +} + +template napi_value IntellVoiceManagerNapi::CreatePropertyBase(napi_env env, T &propertyMap, napi_ref ref) +{ + napi_value result = nullptr; + napi_status status; + string propName; + int32_t enumValue; + napi_value enumNapiValue; + + status = napi_create_object(env, &result); + if (status != napi_ok) { + INTELL_VOICE_LOG_ERROR("failed to create object"); + napi_get_undefined(env, &result); + return result; + } + + for (auto &iter : propertyMap) { + propName = iter.first; + enumValue = iter.second; + + enumNapiValue = SetValue(env, enumValue); + status = napi_set_named_property(env, result, propName.c_str(), enumNapiValue); + if (status != napi_ok) { + break; + } + propName.clear(); + } + + if (status != napi_ok) { + INTELL_VOICE_LOG_ERROR("failed to set base property"); + napi_get_undefined(env, &result); + return result; + } + + status = napi_create_reference(env, result, 1, &ref); + if (status != napi_ok) { + INTELL_VOICE_LOG_ERROR("failed to create base property"); + napi_get_undefined(env, &result); + return result; + } + + INTELL_VOICE_LOG_INFO("create base property success"); + return result; +} + +EXTERN_C_START +static napi_value Export(napi_env env, napi_value exports) +{ + // Export static methods and enum + napi_status status; + napi_property_descriptor staticProperties[] = { + DECLARE_NAPI_STATIC_FUNCTION( + "createEnrollIntelligentVoiceEngine", IntellVoiceManagerNapi::CreateEnrollIntelligentVoiceEngine), + DECLARE_NAPI_STATIC_FUNCTION( + "createWakeupIntelligentVoiceEngine", IntellVoiceManagerNapi::CreateWakeupIntelligentVoiceEngine), + }; + status = + napi_define_properties(env, exports, sizeof(staticProperties) / sizeof(staticProperties[0]), staticProperties); + INTELL_VOICE_LOG_INFO("init static properties, status: %{public}d", status); + + // Export Class + IntellVoiceManagerNapi::Export(env, exports); + + status = napi_set_named_property( + env, exports, ENROLL_ENGINE_NAPI_CLASS_NAME, EnrollIntellVoiceEngineNapi::Constructor(env)); + INTELL_VOICE_LOG_INFO("init %{public}s, status: %{public}d", ENROLL_ENGINE_NAPI_CLASS_NAME, status); + + status = napi_set_named_property( + env, exports, WAKEUP_ENGINE_NAPI_CLASS_NAME, WakeupIntellVoiceEngineNapi::Constructor(env)); + INTELL_VOICE_LOG_INFO("init %{public}s, status: %{public}d", WAKEUP_ENGINE_NAPI_CLASS_NAME, status); + + return exports; +} +EXTERN_C_END + +static napi_module g_module = { + .nm_version = 1, + .nm_flags = 0, + .nm_filename = nullptr, + .nm_register_func = Export, + .nm_modname = "ai.intelligentVoice", + .nm_priv = ((void *)0), + .reserved = {0}, +}; + +extern "C" __attribute__((constructor)) void RegisterModule(void) +{ + napi_module_register(&g_module); +} +} // namespace IntellVoiceNapi +} // namespace OHOS diff --git a/frameworks/js/napi/intell_voice_manager_napi.h b/frameworks/js/napi/intell_voice_manager_napi.h new file mode 100755 index 0000000..910801f --- /dev/null +++ b/frameworks/js/napi/intell_voice_manager_napi.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTELL_VOICE_MANAGER_NAPI_H +#define INTELL_VOICE_MANAGER_NAPI_H + +#include +#include "napi/native_api.h" +#include "napi/native_node_api.h" + +#include "intell_voice_manager.h" + +namespace OHOS { +namespace IntellVoiceNapi { +using OHOS::IntellVoice::IntellVoiceManager; + +class IntellVoiceManagerNapi { +public: + IntellVoiceManagerNapi(); + ~IntellVoiceManagerNapi(); + + static napi_value Export(napi_env env, napi_value exports); + static napi_value CreateEnrollIntelligentVoiceEngine(napi_env env, napi_callback_info info); + static napi_value CreateWakeupIntelligentVoiceEngine(napi_env env, napi_callback_info info); + +private: + static void Destructor(napi_env env, void *nativeObject, void *finalize_hint); + static napi_value Constructor(napi_env env, napi_callback_info info); + + static napi_value GetCapabilityInfo(napi_env env, napi_callback_info info); + static napi_value On(napi_env env, napi_callback_info info); + static napi_value Off(napi_env env, napi_callback_info info); + + static napi_value GetIntelligentVoiceManager(napi_env env, napi_callback_info info); + static napi_value GetIntelligentVoiceManagerWrapper(napi_env env); + template static napi_value CreatePropertyBase(napi_env env, T &propertyMap, napi_ref ref); + + napi_env env_ = nullptr; + napi_ref wrapper_ = nullptr; + IntellVoiceManager *manager_ = nullptr; + static napi_ref serviceChangeTypeRef_; + static napi_ref engineTypeRef_; + static napi_ref sensibilityTypeRef_; + static napi_ref enrollEventTypeRef_; + static napi_ref wakeupEventTypeRef_; + static napi_ref errorCodeRef_; +}; +} // namespace IntellVoiceNapi +} // namespace OHOS +#endif diff --git a/frameworks/js/napi/intell_voice_napi_queue.cpp b/frameworks/js/napi/intell_voice_napi_queue.cpp new file mode 100755 index 0000000..03bf8a7 --- /dev/null +++ b/frameworks/js/napi/intell_voice_napi_queue.cpp @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "intell_voice_napi_queue.h" +#include "intell_voice_napi_util.h" +#include "intell_voice_log.h" + +#define LOG_TAG "IntellVoiceNapiQueue" + +using namespace std; + +namespace OHOS { +namespace IntellVoiceNapi { +AsyncComplete NapiAsync::complete_ = nullptr; + +AsyncContext::AsyncContext() +{ + INTELL_VOICE_LOG_INFO("enter"); +} +AsyncContext::~AsyncContext() +{ + INTELL_VOICE_LOG_INFO("enter"); + if (env_ != nullptr) { + if (work_ != nullptr) { + napi_delete_async_work(env_, work_); + } + if (callbackRef_ != nullptr) { + napi_delete_reference(env_, callbackRef_); + } + env_ = nullptr; + } +} + +void AsyncContext::GetCbInfo(napi_env env, napi_callback_info info, size_t callBackIndex, CbInfoParser parser) +{ + INTELL_VOICE_LOG_INFO("enter"); + napi_value jsThis = nullptr; + const int32_t refCount = 1; + size_t argc = ARGC_MAX; + napi_value args[ARGC_MAX] = {nullptr}; + + env_ = env; + status_ = napi_get_cb_info(env, info, &argc, args, &jsThis, nullptr); + CHECK_STATUS_RETURN_VOID(this, "Failed to get cb info"); + + status_ = napi_unwrap(env, jsThis, &engineNapi_); + CHECK_STATUS_RETURN_VOID(this, "Failed to get engine napi instance"); + + if (argc > callBackIndex) { + napi_valuetype valueType = napi_undefined; + napi_typeof(env, args[callBackIndex], &valueType); + if (valueType == napi_function) { + status_ = napi_create_reference(env, args[callBackIndex], refCount, &callbackRef_); + CHECK_STATUS_RETURN_VOID(this, "Failed to create callback reference"); + } else { + INTELL_VOICE_LOG_ERROR("Failed to get asyncCallback, type mismatch"); + } + } + + if (parser) { + parser(argc, args); + } +} + +napi_value NapiAsync::AsyncWork( + shared_ptr context, const string &name, AsyncExecute execute, AsyncComplete complete) +{ + INTELL_VOICE_LOG_INFO("enter"); + napi_value result = nullptr; + if (context->callbackRef_ == nullptr) { + napi_create_promise(context->env_, &context->deferred_, &result); + } else { + napi_get_undefined(context->env_, &result); + } + + napi_value resource = nullptr; + complete_ = complete; + napi_create_string_utf8(context->env_, name.c_str(), NAPI_AUTO_LENGTH, &resource); + napi_create_async_work(context->env_, + nullptr, + resource, + execute, + AsyncCompleteCallback, + static_cast(context.get()), + &context->work_); + + napi_queue_async_work(context->env_, context->work_); + context->contextSp_ = context; + + return result; +} + +napi_value NapiAsync::AsyncWork( + shared_ptr context, const string &name, AsyncExecute execute, napi_async_complete_callback complete) +{ + INTELL_VOICE_LOG_INFO("enter"); + napi_value result = nullptr; + if (context->callbackRef_ == nullptr) { + napi_create_promise(context->env_, &context->deferred_, &result); + } else { + napi_get_undefined(context->env_, &result); + } + + napi_value resource = nullptr; + napi_create_string_utf8(context->env_, name.c_str(), NAPI_AUTO_LENGTH, &resource); + napi_create_async_work( + context->env_, nullptr, resource, execute, complete, static_cast(context.get()), &context->work_); + + napi_queue_async_work(context->env_, context->work_); + context->contextSp_ = context; + + return result; +} + +void NapiAsync::CommonCallbackRoutine(AsyncContext *context, const napi_value &data) +{ + CHECK_RETURN_VOID(context != nullptr, "async context is null"); + + if (context->deferred_) { + HandlePromise(context, data); + } else { + HandleAsyncCallback(context, data); + } + context->contextSp_.reset(); +} + +void NapiAsync::HandlePromise(AsyncContext *context, const napi_value &data) +{ + napi_value result = nullptr; + napi_value error = nullptr; + napi_get_undefined(context->env_, &result); + napi_get_undefined(context->env_, &error); + + if (context->status_ == napi_ok) { + result = data; + napi_resolve_deferred(context->env_, context->deferred_, result); + return; + } + napi_value message = nullptr; + napi_create_string_utf8(context->env_, context->error_.c_str(), NAPI_AUTO_LENGTH, &message); + napi_create_error(context->env_, nullptr, message, &error); + napi_reject_deferred(context->env_, context->deferred_, error); +} + +void NapiAsync::HandleAsyncCallback(AsyncContext *context, const napi_value &data) +{ + const size_t argc = 2; + napi_value args[argc] = {nullptr, nullptr}; + napi_value callback = nullptr; + napi_value ret = nullptr; + if (context->status_ == napi_ok) { + napi_get_undefined(context->env_, &args[0]); + args[1] = data; + } else { + napi_value message = nullptr; + napi_create_string_utf8(context->env_, context->error_.c_str(), NAPI_AUTO_LENGTH, &message); + napi_create_error(context->env_, nullptr, message, &args[0]); + napi_get_undefined(context->env_, &args[1]); + } + napi_get_reference_value(context->env_, context->callbackRef_, &callback); + napi_call_function(context->env_, nullptr, callback, argc, args, &ret); +} + +void NapiAsync::AsyncCompleteCallback(napi_env env, napi_status status, void *data) +{ + INTELL_VOICE_LOG_INFO("enter"); + CHECK_RETURN_VOID(data != nullptr, "async complete callback data is null"); + napi_value result = nullptr; + napi_get_undefined(env, &result); + auto context = static_cast(data); + if ((status != napi_ok) && (context->status_ == napi_ok)) { + context->status_ = status; + } + + if (context->status_ == napi_ok && (complete_ != nullptr)) { + complete_(context, result); + } + CommonCallbackRoutine(context, result); +} +} // namespace IntellVoiceNapi +} // namespace OHOS diff --git a/frameworks/js/napi/intell_voice_napi_queue.h b/frameworks/js/napi/intell_voice_napi_queue.h new file mode 100755 index 0000000..f6d07d9 --- /dev/null +++ b/frameworks/js/napi/intell_voice_napi_queue.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTELL_VOICE_NAPI_QUEUE_H +#define INTELL_VOICE_NAPI_QUEUE_H + +#include +#include "napi/native_api.h" +#include "napi/native_node_api.h" + +namespace OHOS { +namespace IntellVoiceNapi { +constexpr size_t ARGC_MAX = 4; + +using CbInfoParser = std::function; + +#define CHECK_STATUS_RETURN_VOID(context, message) \ + do { \ + if ((context)->status_ != napi_ok) { \ + (context)->error_ = std::string(message); \ + INTELL_VOICE_LOG_ERROR(message); \ + return; \ + } \ + } while (0) + +class AsyncContext { +public: + AsyncContext(); + ~AsyncContext(); + void GetCbInfo(napi_env env, napi_callback_info info, size_t callBackIndex, CbInfoParser parser); + + napi_env env_ = nullptr; + void *engineNapi_ = nullptr; + + napi_status status_ = napi_invalid_arg; + std::string error_; + int32_t result_ = -1; + +private: + napi_async_work work_ = nullptr; + napi_deferred deferred_ = nullptr; + napi_ref callbackRef_ = nullptr; + std::shared_ptr contextSp_ = nullptr; + + friend class NapiAsync; +}; + +using AsyncExecute = napi_async_execute_callback; +using AsyncComplete = std::function; + +class NapiAsync { +public: + static napi_value AsyncWork(std::shared_ptr context, const std::string &name, AsyncExecute execute, + AsyncComplete complete = nullptr); + static napi_value AsyncWork(std::shared_ptr context, const std::string &name, AsyncExecute execute, + napi_async_complete_callback complete); + static void CommonCallbackRoutine(AsyncContext *context, const napi_value &data); + +private: + static void AsyncCompleteCallback(napi_env env, napi_status status, void *data); + static void HandlePromise(AsyncContext *context, const napi_value &data); + static void HandleAsyncCallback(AsyncContext *context, const napi_value &data); + + static AsyncComplete complete_; +}; +} // namespace IntellVoiceNapi +} // namespace OHOS + +#endif diff --git a/frameworks/js/napi/intell_voice_napi_util.cpp b/frameworks/js/napi/intell_voice_napi_util.cpp new file mode 100755 index 0000000..f509bc2 --- /dev/null +++ b/frameworks/js/napi/intell_voice_napi_util.cpp @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "intell_voice_napi_util.h" +#include "intell_voice_log.h" + +#define LOG_TAG "IntellVoiceNapiUtil" + +using namespace std; + +namespace OHOS { +namespace IntellVoiceNapi { +static const int32_t MAX_STRING_BUFFSIZE = 1024; + +IntellVoiceRef::IntellVoiceRef(napi_env env, napi_value value) +{ + INTELL_VOICE_LOG_INFO("enter"); + env_ = env; + napi_create_reference(env_, value, 1, &ref_); +} + +IntellVoiceRef::~IntellVoiceRef() +{ + INTELL_VOICE_LOG_INFO("enter"); + if (env_ != nullptr && ref_ != nullptr) { + napi_delete_reference(env_, ref_); + } + env_ = nullptr; + ref_ = nullptr; +} + +napi_value IntellVoiceRef::GetRefValue() +{ + napi_value value = nullptr; + napi_status status = napi_get_reference_value(env_, ref_, &value); + if (status != napi_ok || value == nullptr) { + INTELL_VOICE_LOG_ERROR("get reference value fail"); + return nullptr; + } + return value; +} + +napi_value SetValue(napi_env env, const int32_t &value) +{ + napi_value result = nullptr; + napi_status status = napi_create_int32(env, value, &result); + if (status != napi_ok || result == nullptr) { + INTELL_VOICE_LOG_ERROR("get js value fail"); + return nullptr; + } + return result; +} + +napi_value SetValue(napi_env env, const string &value) +{ + napi_value result = nullptr; + napi_status status = napi_create_string_utf8(env, value.c_str(), value.size(), &result); + if (status != napi_ok || result == nullptr) { + INTELL_VOICE_LOG_ERROR("get js value fail"); + return nullptr; + } + return result; +} + +napi_status GetValue(napi_env env, napi_value jsValue, int32_t &value) +{ + napi_valuetype valueType = napi_undefined; + napi_typeof(env, jsValue, &valueType); + if (valueType != napi_number) { + return napi_generic_failure; + } + return napi_get_value_int32(env, jsValue, &value); +} + +napi_status GetValue(napi_env env, napi_value jsValue, bool &value) +{ + napi_valuetype valueType = napi_undefined; + napi_typeof(env, jsValue, &valueType); + if (valueType != napi_boolean) { + return napi_generic_failure; + } + return napi_get_value_bool(env, jsValue, &value); +} + +napi_status GetValue(napi_env env, napi_value jsValue, string &value) +{ + size_t bufferSize = 0; + napi_valuetype valueType = napi_undefined; + napi_typeof(env, jsValue, &valueType); + if (valueType != napi_string) { + return napi_generic_failure; + } + napi_status status = napi_get_value_string_utf8(env, jsValue, nullptr, 0, &bufferSize); + if (status != napi_ok || bufferSize == 0 || bufferSize >= MAX_STRING_BUFFSIZE) { + INTELL_VOICE_LOG_ERROR("failed to get buffersize"); + return napi_generic_failure; + } + + char *buffer = (char *)malloc((bufferSize + 1) * sizeof(char)); + if (buffer == nullptr) { + INTELL_VOICE_LOG_ERROR("no memory"); + return napi_generic_failure; + } + + status = napi_get_value_string_utf8(env, jsValue, buffer, bufferSize + 1, &bufferSize); + value = buffer; + free(buffer); + buffer = nullptr; + return status; +} +} // namespace IntellVoiceNapi +} // namespace OHOS diff --git a/frameworks/js/napi/intell_voice_napi_util.h b/frameworks/js/napi/intell_voice_napi_util.h new file mode 100755 index 0000000..2076ac4 --- /dev/null +++ b/frameworks/js/napi/intell_voice_napi_util.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTELL_VOICE_NAPI_UTIL_H +#define INTELL_VOICE_NAPI_UTIL_H + +#include "napi/native_api.h" +#include "napi/native_node_api.h" + +namespace OHOS { +namespace IntellVoiceNapi { +#define CHECK_RETURN_VOID(condition, message) \ + do { \ + if (!(condition)) { \ + INTELL_VOICE_LOG_ERROR(message); \ + return; \ + } \ + } while (0) + +class IntellVoiceRef { +public: + IntellVoiceRef(napi_env env, napi_value value); + ~IntellVoiceRef(); + napi_value GetRefValue(); + +private: + napi_env env_ = nullptr; + napi_ref ref_ = nullptr; +}; + +napi_value SetValue(napi_env env, const int32_t &value); +napi_value SetValue(napi_env env, const std::string &value); + +napi_status GetValue(napi_env env, napi_value jsValue, int32_t &value); +napi_status GetValue(napi_env env, napi_value jsValue, bool &value); +napi_status GetValue(napi_env env, napi_value jsValue, std::string &value); +} // namespace IntellVoiceNapi +} // namespace OHOS +#endif diff --git a/frameworks/js/napi/wakeup_intell_voice_engine_napi.cpp b/frameworks/js/napi/wakeup_intell_voice_engine_napi.cpp new file mode 100755 index 0000000..2365c82 --- /dev/null +++ b/frameworks/js/napi/wakeup_intell_voice_engine_napi.cpp @@ -0,0 +1,444 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "wakeup_intell_voice_engine_napi.h" + +#include "want.h" +#include "iservice_registry.h" +#include "system_ability_definition.h" + +#include "intell_voice_napi_util.h" +#include "intell_voice_napi_queue.h" + +#include "intell_voice_log.h" +#include "i_intell_voice_engine_callback.h" + +#define LOG_TAG "WakeupIntellVoiceEngineNapi" + +using namespace std; +using namespace OHOS::IntellVoice; + +namespace OHOS { +namespace IntellVoiceNapi { +static const std::string INTELL_VOICE_EVENT_CALLBACK_NAME = "IntellVoiceEvent"; + +WakeupIntellVoiceEngineNapi::WakeupIntellVoiceEngineNapi() +{ + INTELL_VOICE_LOG_INFO("enter, %{public}p", this); +} + +WakeupIntellVoiceEngineNapi::~WakeupIntellVoiceEngineNapi() +{ + INTELL_VOICE_LOG_INFO("enter"); + if (wrapper_ != nullptr) { + napi_delete_reference(env_, wrapper_); + } +} + +napi_value WakeupIntellVoiceEngineNapi::New(napi_env env, napi_callback_info info) +{ + INTELL_VOICE_LOG_INFO("enter"); + size_t argc = 1; + napi_value args[1] = {nullptr}; + + napi_value jsThis = nullptr; + napi_value undefinedResult = nullptr; + napi_get_undefined(env, &undefinedResult); + + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &jsThis, nullptr)); + + unique_ptr engineNapi = make_unique(); + if (engineNapi == nullptr) { + INTELL_VOICE_LOG_ERROR("Failed to create WakeupIntellVoiceEngineNapi, No memory."); + return undefinedResult; + } + engineNapi->env_ = env; + + WakeupIntelligentVoiceEngineDescriptor descriptor = {}; + napi_value value = nullptr; + if (napi_get_named_property(env, args[0], "needApAlgEngine", &value) == napi_ok) { + GetValue(env, value, descriptor.needApAlgEngine); + } + if (napi_get_named_property(env, args[0], "wakeupPhrase", &value) == napi_ok) { + GetValue(env, value, descriptor.wakeupPhrase); + } + INTELL_VOICE_LOG_INFO("EngineDescriptor needApAlgEngine: %{public}d", descriptor.needApAlgEngine); + INTELL_VOICE_LOG_INFO("EngineDescriptor wakeupPhrase: %{public}s", descriptor.wakeupPhrase.c_str()); + + engineNapi->engine_ = std::make_shared(descriptor); + if (engineNapi->engine_ == nullptr) { + INTELL_VOICE_LOG_ERROR("create intell voice engine faild."); + return undefinedResult; + } + + auto finalize = [](napi_env env, void *data, void *hint) { + INTELL_VOICE_LOG_INFO("WakeupIntellVoiceEngineNapi finalize callback"); + if (data != nullptr) { + auto obj = static_cast(data); + delete obj; + } + }; + + NAPI_CALL(env, + napi_wrap(env, jsThis, static_cast(engineNapi.get()), finalize, nullptr, &(engineNapi->wrapper_))); + engineNapi.release(); + return jsThis; +} + +napi_value WakeupIntellVoiceEngineNapi::Constructor(napi_env env) +{ + INTELL_VOICE_LOG_INFO("enter"); + napi_status status; + napi_value constructor; + napi_get_undefined(env, &constructor); + + napi_property_descriptor properties[] = { + DECLARE_NAPI_FUNCTION("getSupportedRegions", GetSupportedRegions), + DECLARE_NAPI_FUNCTION("setSensibility", SetSensibility), + DECLARE_NAPI_FUNCTION("setWakeupHapInfo", SetWakeupHapInfo), + DECLARE_NAPI_FUNCTION("setParameter", SetParameter), + DECLARE_NAPI_FUNCTION("getParameter", GetParameter), + DECLARE_NAPI_FUNCTION("release", Release), + DECLARE_NAPI_FUNCTION("on", On), + DECLARE_NAPI_FUNCTION("off", Off), + }; + + status = napi_define_class(env, + WAKEUP_ENGINE_NAPI_CLASS_NAME, + NAPI_AUTO_LENGTH, + New, + nullptr, + sizeof(properties) / sizeof(properties[0]), + properties, + &constructor); + + return constructor; +} + +napi_value WakeupIntellVoiceEngineNapi::GetSupportedRegions(napi_env env, napi_callback_info info) +{ + INTELL_VOICE_LOG_INFO("enter"); + size_t cbIndex = 0; + shared_ptr context = make_shared(); + if (context == nullptr) { + INTELL_VOICE_LOG_ERROR("create AsyncContext faild, No memory"); + return nullptr; + } + + context->GetCbInfo(env, info, cbIndex, nullptr); + + AsyncExecute execute = [](napi_env env, void *data) { + auto asyncContext = static_cast(data); + asyncContext->status_ = napi_ok; + }; + + AsyncComplete complete = [](AsyncContext *context, napi_value &result) { + INTELL_VOICE_LOG_INFO("get supported regions complete"); + napi_create_array(context->env_, &result); + napi_set_element(context->env_, result, 0, SetValue(context->env_, "CN")); + }; + + return NapiAsync::AsyncWork(context, "GetSupportedRegions", execute, complete); +} + +napi_value WakeupIntellVoiceEngineNapi::SetParameter(napi_env env, napi_callback_info info) +{ + INTELL_VOICE_LOG_INFO("enter"); + size_t cbIndex = 2; + class SetParameterContext : public AsyncContext { + public: + string key; + string value; + }; + auto context = make_shared(); + if (context == nullptr) { + INTELL_VOICE_LOG_ERROR("create SetParameterContext faild, No memory"); + return nullptr; + } + + CbInfoParser parser = [env, context](size_t argc, napi_value *argv) { + context->status_ = GetValue(env, argv[0], context->key); + CHECK_STATUS_RETURN_VOID(context, "Failed to get key"); + context->status_ = GetValue(env, argv[1], context->value); + CHECK_STATUS_RETURN_VOID(context, "Failed to get value"); + }; + + context->GetCbInfo(env, info, cbIndex, parser); + + AsyncExecute execute = [](napi_env env, void *data) { + auto asyncContext = static_cast(data); + auto engine = reinterpret_cast(asyncContext->engineNapi_)->engine_; + if (engine == nullptr) { + INTELL_VOICE_LOG_ERROR("get engine instance faild"); + return; + } + asyncContext->result_ = engine->SetParameter(asyncContext->key, asyncContext->value); + asyncContext->status_ = napi_ok; + }; + + return NapiAsync::AsyncWork(context, "SetParameter", execute); +} + +napi_value WakeupIntellVoiceEngineNapi::GetParameter(napi_env env, napi_callback_info info) +{ + INTELL_VOICE_LOG_INFO("enter"); + size_t cbIndex = 1; + shared_ptr context = make_shared(); + if (context == nullptr) { + INTELL_VOICE_LOG_ERROR("create AsyncContext faild, No memory"); + return nullptr; + } + + context->GetCbInfo(env, info, cbIndex, nullptr); + + AsyncExecute execute = [](napi_env env, void *data) { + auto asyncContext = static_cast(data); + asyncContext->status_ = napi_ok; + }; + + AsyncComplete complete = [](AsyncContext *context, napi_value &result) { + INTELL_VOICE_LOG_INFO("get parameter complete"); + result = SetValue(context->env_, "value"); + }; + return NapiAsync::AsyncWork(context, "GetParameter", execute, complete); +} + +napi_value WakeupIntellVoiceEngineNapi::SetSensibility(napi_env env, napi_callback_info info) +{ + INTELL_VOICE_LOG_INFO("enter"); + size_t cbIndex = 1; + class SetSensibilityContext : public AsyncContext { + public: + int32_t sensibility; + }; + auto context = make_shared(); + if (context == nullptr) { + INTELL_VOICE_LOG_ERROR("create SetSensibilityContext faild, No memory"); + return nullptr; + } + + CbInfoParser parser = [env, context](size_t argc, napi_value *argv) { + context->status_ = GetValue(env, argv[0], context->sensibility); + CHECK_STATUS_RETURN_VOID(context, "Failed to get sensibility"); + }; + + context->GetCbInfo(env, info, cbIndex, parser); + + AsyncExecute execute = [](napi_env env, void *data) { + auto asyncContext = static_cast(data); + auto engine = reinterpret_cast(asyncContext->engineNapi_)->engine_; + if (engine == nullptr) { + INTELL_VOICE_LOG_ERROR("get engine instance faild"); + return; + } + asyncContext->result_ = engine->SetSensibility(asyncContext->sensibility); + asyncContext->status_ = napi_ok; + }; + + return NapiAsync::AsyncWork(context, "SetSensibility", execute); +} + +napi_value WakeupIntellVoiceEngineNapi::SetWakeupHapInfo(napi_env env, napi_callback_info info) +{ + INTELL_VOICE_LOG_INFO("enter"); + size_t cbIndex = 1; + class SetWakeupHapContext : public AsyncContext { + public: + WakeupHapInfo hapInfo; + }; + auto context = make_shared(); + if (context == nullptr) { + INTELL_VOICE_LOG_ERROR("create SetWakeupHapContext faild, No memory"); + return nullptr; + } + + CbInfoParser parser = [env, context](size_t argc, napi_value *argv) { + napi_value temp = nullptr; + if (napi_get_named_property(env, argv[0], "bundleName", &temp) == napi_ok) { + GetValue(env, temp, context->hapInfo.bundleName); + } + if (napi_get_named_property(env, argv[0], "abilityName", &temp) == napi_ok) { + GetValue(env, temp, context->hapInfo.abilityName); + } + }; + + context->GetCbInfo(env, info, cbIndex, parser); + + AsyncExecute execute = [](napi_env env, void *data) { + auto asyncContext = static_cast(data); + auto engine = reinterpret_cast(asyncContext->engineNapi_)->engine_; + if (engine == nullptr) { + INTELL_VOICE_LOG_ERROR("get engine instance faild"); + return; + } + asyncContext->result_ = engine->SetWakeupHapInfo(asyncContext->hapInfo); + asyncContext->status_ = napi_ok; + }; + + return NapiAsync::AsyncWork(context, "SetWakeupHapInfo", execute); +} + +napi_value WakeupIntellVoiceEngineNapi::Release(napi_env env, napi_callback_info info) +{ + INTELL_VOICE_LOG_INFO("enter"); + size_t cbIndex = 0; + shared_ptr context = make_shared(); + if (context == nullptr) { + INTELL_VOICE_LOG_ERROR("create AsyncContext faild, No memory"); + return nullptr; + } + + context->GetCbInfo(env, info, cbIndex, nullptr); + + AsyncExecute execute = [](napi_env env, void *data) { + auto asyncContext = static_cast(data); + auto engine = reinterpret_cast(asyncContext->engineNapi_)->engine_; + if (engine == nullptr) { + INTELL_VOICE_LOG_ERROR("get engine instance faild"); + return; + } + asyncContext->result_ = engine->Release(); + asyncContext->status_ = napi_ok; + reinterpret_cast(asyncContext->engineNapi_)->engine_ = nullptr; + }; + + AsyncComplete complete = [](AsyncContext *context, napi_value &result) { + INTELL_VOICE_LOG_INFO("release engine complete"); + }; + return NapiAsync::AsyncWork(context, "Release", execute, complete); +} + +napi_value WakeupIntellVoiceEngineNapi::On(napi_env env, napi_callback_info info) +{ + INTELL_VOICE_LOG_INFO("enter"); + + napi_value undefinedResult = nullptr; + napi_get_undefined(env, &undefinedResult); + + const size_t expectArgCount = 2; + size_t argCount = 2; + napi_value args[expectArgCount] = {0}; + napi_value jsThis = nullptr; + + napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr); + if (status != napi_ok || argCount != expectArgCount) { + INTELL_VOICE_LOG_ERROR("failed to get parameters"); + return undefinedResult; + } + + napi_valuetype eventType = napi_undefined; + if (napi_typeof(env, args[0], &eventType) != napi_ok || eventType != napi_string) { + INTELL_VOICE_LOG_ERROR("callback event name type mismatch"); + return undefinedResult; + } + + string callbackName = ""; + status = GetValue(env, args[0], callbackName); + if (status != napi_ok) { + INTELL_VOICE_LOG_ERROR("failed to get callbackName"); + return undefinedResult; + } + INTELL_VOICE_LOG_INFO("callbackName: %{public}s", callbackName.c_str()); + + napi_valuetype handler = napi_undefined; + if (napi_typeof(env, args[1], &handler) != napi_ok || handler != napi_function) { + INTELL_VOICE_LOG_ERROR("callback handler type mismatch"); + return undefinedResult; + } + + return RegisterCallback(env, jsThis, args); +} + +napi_value WakeupIntellVoiceEngineNapi::RegisterCallback(napi_env env, napi_value jsThis, napi_value *args) +{ + INTELL_VOICE_LOG_INFO("enter"); + napi_value result = nullptr; + napi_get_undefined(env, &result); + + WakeupIntellVoiceEngineNapi *engineNapi = nullptr; + napi_status status = napi_unwrap(env, jsThis, reinterpret_cast(&engineNapi)); + if (status != napi_ok || engineNapi == nullptr) { + INTELL_VOICE_LOG_ERROR("Failed to get engine napi instance"); + return result; + } + + if (engineNapi->engine_ == nullptr) { + INTELL_VOICE_LOG_ERROR("engine is null"); + return result; + } + + engineNapi->callbackNapi_ = make_shared(env, args[1]); + engineNapi->engine_->SetCallback(engineNapi->callbackNapi_); + INTELL_VOICE_LOG_INFO("Set callback finish"); + return result; +} + +napi_value WakeupIntellVoiceEngineNapi::Off(napi_env env, napi_callback_info info) +{ + INTELL_VOICE_LOG_INFO("enter"); + + napi_value undefinedResult = nullptr; + napi_get_undefined(env, &undefinedResult); + + const size_t expectArgCount = 1; + size_t argCount = 1; + napi_value args[expectArgCount] = {0}; + napi_value jsThis = nullptr; + + napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr); + if (status != napi_ok || argCount != expectArgCount) { + INTELL_VOICE_LOG_ERROR("failed to get parameters"); + return undefinedResult; + } + + napi_valuetype eventType = napi_undefined; + if (napi_typeof(env, args[0], &eventType) != napi_ok || eventType != napi_string) { + INTELL_VOICE_LOG_ERROR("callback event name type mismatch"); + return undefinedResult; + } + + string callbackName = ""; + status = GetValue(env, args[0], callbackName); + if (status != napi_ok) { + INTELL_VOICE_LOG_ERROR("failed to get callbackName"); + return undefinedResult; + } + INTELL_VOICE_LOG_INFO("callbackName: %{public}s", callbackName.c_str()); + + return UnregisterCallback(env, jsThis, callbackName); +} + +napi_value WakeupIntellVoiceEngineNapi::UnregisterCallback(napi_env env, napi_value jsThis, const string &callbackName) +{ + INTELL_VOICE_LOG_INFO("enter"); + napi_value result = nullptr; + napi_get_undefined(env, &result); + + WakeupIntellVoiceEngineNapi *engineNapi = nullptr; + napi_status status = napi_unwrap(env, jsThis, reinterpret_cast(&engineNapi)); + if (status != napi_ok || engineNapi == nullptr) { + INTELL_VOICE_LOG_ERROR("Failed to get engine napi instance"); + return result; + } + + if (callbackName != INTELL_VOICE_EVENT_CALLBACK_NAME) { + INTELL_VOICE_LOG_ERROR("No such off callback supported"); + return result; + } + + return result; +} +} // namespace IntellVoiceNapi +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/js/napi/wakeup_intell_voice_engine_napi.h b/frameworks/js/napi/wakeup_intell_voice_engine_napi.h new file mode 100755 index 0000000..d207d56 --- /dev/null +++ b/frameworks/js/napi/wakeup_intell_voice_engine_napi.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef WAKEUP_INTELL_VOICE_ENGINE_NAPI_H +#define WAKEUP_INTELL_VOICE_ENGINE_NAPI_H + +#include "napi/native_api.h" +#include "napi/native_node_api.h" +#include "engine_event_callback_napi.h" +#include "wakeup_intell_voice_engine.h" + +#define WAKEUP_ENGINE_NAPI_CLASS_NAME "WakeupIntelligentVoiceEngine" + +namespace OHOS { +namespace IntellVoiceNapi { +using OHOS::IntellVoice::WakeupIntellVoiceEngine; + +class WakeupIntellVoiceEngineNapi { +public: + WakeupIntellVoiceEngineNapi(); + ~WakeupIntellVoiceEngineNapi(); + + static napi_value Constructor(napi_env env); + + static napi_value GetSupportedRegions(napi_env env, napi_callback_info info); + static napi_value SetSensibility(napi_env env, napi_callback_info info); + static napi_value SetWakeupHapInfo(napi_env env, napi_callback_info info); + static napi_value SetParameter(napi_env env, napi_callback_info info); + static napi_value GetParameter(napi_env env, napi_callback_info info); + static napi_value Release(napi_env env, napi_callback_info info); + static napi_value On(napi_env env, napi_callback_info info); + static napi_value Off(napi_env env, napi_callback_info info); + + std::shared_ptr engine_ = nullptr; + std::shared_ptr callbackNapi_ = nullptr; + +private: + static napi_value New(napi_env env, napi_callback_info info); + + static napi_value RegisterCallback(napi_env env, napi_value jsThis, napi_value *args); + static napi_value UnregisterCallback(napi_env env, napi_value jsThis, const std::string &callbackName); + +private: + napi_env env_ = nullptr; + napi_ref wrapper_ = nullptr; +}; +} // namespace IntellVoiceNapi +} // namespace OHOS + +#endif diff --git a/frameworks/native/BUILD.gn b/frameworks/native/BUILD.gn new file mode 100755 index 0000000..d09c633 --- /dev/null +++ b/frameworks/native/BUILD.gn @@ -0,0 +1,52 @@ +# Copyright (c) 2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") + +ohos_shared_library("intellvoice_native") { + sources = [ + "enroll_intell_voice_engine.cpp", + "intell_voice_manager.cpp", + "wakeup_intell_voice_engine.cpp", + ] + + include_dirs = [ + "//foundation/ai/intelligent_voice_framework/interfaces/inner_api/native", + "//foundation/ai/intelligent_voice_framework/services/intell_voice_engine", + "//foundation/ai/intelligent_voice_framework/services/intell_voice_engine/proxy", + "//foundation/ai/intelligent_voice_framework/utils", + ] + + cflags_cc = [ + "-Wno-error=unused-parameter", + "-DHILOG_ENABLE", + "-DENABLE_DEBUG", + ] + + deps = [ + "//foundation/ai/intelligent_voice_framework/services:intell_voice_proxy", + ] + + external_deps = [ + "ability_base:base", + "ability_base:want", + "c_utils:utils", + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + "safwk:system_ability_fwk", + "samgr:samgr_proxy", + ] + + subsystem_name = "ai" + part_name = "intelligent_voice_framework" +} diff --git a/frameworks/native/enroll_intell_voice_engine.cpp b/frameworks/native/enroll_intell_voice_engine.cpp new file mode 100755 index 0000000..9367d45 --- /dev/null +++ b/frameworks/native/enroll_intell_voice_engine.cpp @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "enroll_intell_voice_engine.h" +#include "i_intell_voice_engine.h" +#include "intell_voice_manager.h" +#include "intell_voice_log.h" + +#define LOG_TAG "EnrollIntellVoiceEngine" +using namespace std; +using namespace OHOS::IntellVoiceEngine; + +namespace OHOS { +namespace IntellVoice { +static constexpr int32_t MIN_BUFFER_SIZE = 1280; // 16 * 2 * 40ms +static constexpr int32_t CHANNEL_CNT = 1; +static constexpr int32_t BITS_PER_SAMPLE = 16; +static constexpr int32_t SAMPLE_RATE = 16000; + +EnrollIntellVoiceEngine::EnrollIntellVoiceEngine(const EnrollIntelligentVoiceEngineDescriptor &descriptor) +{ + INTELL_VOICE_LOG_INFO("enter"); + + descriptor_ = make_unique(); + if (descriptor_ != nullptr) { + descriptor_->wakeupPhrase = descriptor.wakeupPhrase; + } + IntellVoiceManager::GetInstance()->CreateIntellVoiceEngine(INTELL_VOICE_ENROLL, engine_); +} + +EnrollIntellVoiceEngine::~EnrollIntellVoiceEngine() +{ + INTELL_VOICE_LOG_INFO("enter"); + IntellVoiceManager::GetInstance()->ReleaseIntellVoiceEngine(INTELL_VOICE_ENROLL); +} + +int32_t EnrollIntellVoiceEngine::Init(const EngineConfig &config) +{ + INTELL_VOICE_LOG_INFO("enter"); + if (engine_ == nullptr) { + INTELL_VOICE_LOG_ERROR("IntellVoiceEngine is null"); + return -1; + } + + IntellVoiceEngineInfo info = {}; + info.wakeupPhrase = descriptor_->wakeupPhrase; + info.isPcmFromExternal = false; + info.minBufSize = MIN_BUFFER_SIZE; + info.sampleChannels = CHANNEL_CNT; + info.bitsPerSample = BITS_PER_SAMPLE; + info.sampleRate = SAMPLE_RATE; + + return engine_->Attach(info); +} + +int32_t EnrollIntellVoiceEngine::Start(const bool &isLast) +{ + INTELL_VOICE_LOG_INFO("enter"); + if (engine_ == nullptr) { + INTELL_VOICE_LOG_ERROR("engine is null"); + return -1; + } + return engine_->Start(isLast); +} + +int32_t EnrollIntellVoiceEngine::Stop() +{ + INTELL_VOICE_LOG_INFO("enter"); + if (engine_ == nullptr) { + INTELL_VOICE_LOG_ERROR("engine is null"); + return -1; + } + return engine_->Stop(); +} + +int32_t EnrollIntellVoiceEngine::Commit() +{ + INTELL_VOICE_LOG_INFO("enter"); + if (engine_ == nullptr) { + INTELL_VOICE_LOG_ERROR("engine is null"); + return -1; + } + string keyValueList = "CommitEnrollment=true"; + return engine_->SetParameter(keyValueList); +} + +int32_t EnrollIntellVoiceEngine::SetSensibility(const int32_t &sensibility) +{ + INTELL_VOICE_LOG_INFO("enter"); + if (engine_ == nullptr) { + INTELL_VOICE_LOG_ERROR("engine is null"); + return -1; + } + string keyValueList = "Sensibility=" + to_string(sensibility); + return engine_->SetParameter(keyValueList); +} + +int32_t EnrollIntellVoiceEngine::SetWakeupHapInfo(const WakeupHapInfo &info) +{ + INTELL_VOICE_LOG_INFO("enter"); + int32_t ret; + if (engine_ == nullptr) { + INTELL_VOICE_LOG_ERROR("engine is null"); + return -1; + } + ret = engine_->SetParameter("wakeup_bundle_name=" + info.bundleName); + ret = engine_->SetParameter("wakeup_ability_name=" + info.abilityName); + return ret; +} + +int32_t EnrollIntellVoiceEngine::SetParameter(const string &key, const string &value) +{ + INTELL_VOICE_LOG_INFO("enter"); + if (engine_ == nullptr) { + INTELL_VOICE_LOG_ERROR("engine is null"); + return -1; + } + string keyValueList = key + "=" + value; + return engine_->SetParameter(keyValueList); +} + +int32_t EnrollIntellVoiceEngine::Release() +{ + INTELL_VOICE_LOG_INFO("enter"); + if (engine_ == nullptr) { + INTELL_VOICE_LOG_ERROR("engine is null"); + return -1; + } + + return engine_->Detach(); +} + +int32_t EnrollIntellVoiceEngine::SetCallback(shared_ptr callback) +{ + INTELL_VOICE_LOG_INFO("enter"); + if (engine_ == nullptr) { + INTELL_VOICE_LOG_ERROR("engine is null"); + return -1; + } + + callback_ = sptr(new (std::nothrow) EngineCallbackInner()); + if (callback_ == nullptr) { + INTELL_VOICE_LOG_ERROR("callback_ is nullptr"); + return -1; + } + callback_->SetEngineEventCallback(callback); + engine_->SetCallback(callback_->AsObject()); + return 0; +} +} +} \ No newline at end of file diff --git a/frameworks/native/intell_voice_manager.cpp b/frameworks/native/intell_voice_manager.cpp new file mode 100755 index 0000000..3b0b6e7 --- /dev/null +++ b/frameworks/native/intell_voice_manager.cpp @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "intell_voice_manager.h" +#include "iservice_registry.h" +#include "system_ability_definition.h" +#include "intell_voice_log.h" +#include "i_intell_voice_service.h" +#include "intell_voice_service_proxy.h" + +using namespace std; +using namespace OHOS::IntellVoiceEngine; +#define LOG_TAG "IntellVoiceManager" + +namespace OHOS { +namespace IntellVoice { +static sptr g_sProxy = nullptr; + +IntellVoiceManager::IntellVoiceManager() +{ + Init(); +} + +IntellVoiceManager::~IntellVoiceManager() +{ + INTELL_VOICE_LOG_INFO("enter"); +} + +IntellVoiceManager *IntellVoiceManager::GetInstance() +{ + static IntellVoiceManager manager; + return &manager; +} + +void IntellVoiceManager::Init() +{ + auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (samgr == nullptr) { + INTELL_VOICE_LOG_ERROR("get sa manager failed"); + return; + } + + sptr object = samgr->GetSystemAbility(INTELL_VOICE_SERVICE_ID); + if (object == nullptr) { + INTELL_VOICE_LOG_ERROR("get system ability failed"); + return; + } + g_sProxy = iface_cast(object); + if (g_sProxy == nullptr) { + INTELL_VOICE_LOG_ERROR("init Service Proxy failed."); + } else { + INTELL_VOICE_LOG_INFO("init Service Proxy success."); + } +} + +int32_t IntellVoiceManager::CreateIntellVoiceEngine(IntellVoiceEngineType type, sptr &inst) +{ + INTELL_VOICE_LOG_INFO("enter"); + if (g_sProxy == nullptr) { + INTELL_VOICE_LOG_ERROR("IntellVoiceService Proxy is null."); + return -1; + } + return g_sProxy->CreateIntellVoiceEngine(type, inst); +} + +int32_t IntellVoiceManager::ReleaseIntellVoiceEngine(IntellVoiceEngineType type) +{ + INTELL_VOICE_LOG_INFO("enter"); + if (g_sProxy == nullptr) { + INTELL_VOICE_LOG_ERROR("IntellVoiceService Proxy is null."); + return -1; + } + return g_sProxy->ReleaseIntellVoiceEngine(type); +} +} +} \ No newline at end of file diff --git a/frameworks/native/wakeup_intell_voice_engine.cpp b/frameworks/native/wakeup_intell_voice_engine.cpp new file mode 100755 index 0000000..0f25677 --- /dev/null +++ b/frameworks/native/wakeup_intell_voice_engine.cpp @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "wakeup_intell_voice_engine.h" +#include "i_intell_voice_engine.h" +#include "intell_voice_manager.h" +#include "intell_voice_log.h" + +using namespace std; +#define LOG_TAG "WakeupIntellVoiceEngine" + +namespace OHOS { +namespace IntellVoice { +WakeupIntellVoiceEngine::WakeupIntellVoiceEngine(const WakeupIntelligentVoiceEngineDescriptor &descriptor) +{ + INTELL_VOICE_LOG_INFO("enter"); + + descriptor_ = make_unique(); + descriptor_->needApAlgEngine = descriptor.needApAlgEngine; + descriptor_->wakeupPhrase = descriptor.wakeupPhrase; + IntellVoiceManager::GetInstance()->CreateIntellVoiceEngine(INTELL_VOICE_WAKEUP, engine_); +} + +WakeupIntellVoiceEngine::~WakeupIntellVoiceEngine() +{ + INTELL_VOICE_LOG_INFO("enter"); + IntellVoiceManager::GetInstance()->ReleaseIntellVoiceEngine(INTELL_VOICE_WAKEUP); +} + +int32_t WakeupIntellVoiceEngine::SetSensibility(const int32_t &sensibility) +{ + INTELL_VOICE_LOG_INFO("enter"); + if (engine_ == nullptr) { + INTELL_VOICE_LOG_ERROR("engine is null"); + return -1; + } + string keyValueList = "Sensibility=" + to_string(sensibility); + return engine_->SetParameter(keyValueList); +} + +int32_t WakeupIntellVoiceEngine::SetWakeupHapInfo(const WakeupHapInfo &info) +{ + INTELL_VOICE_LOG_INFO("enter"); + int32_t ret; + if (engine_ == nullptr) { + INTELL_VOICE_LOG_ERROR("engine is null"); + return -1; + } + ret = engine_->SetParameter("wakeup_bundle_name=" + info.bundleName); + ret = engine_->SetParameter("wakeup_ability_name=" + info.abilityName); + return ret; +} + +int32_t WakeupIntellVoiceEngine::SetParameter(const string &key, const string &value) +{ + INTELL_VOICE_LOG_INFO("enter"); + if (engine_ == nullptr) { + INTELL_VOICE_LOG_ERROR("engine is null"); + return -1; + } + string keyValueList = key + "=" + value; + return engine_->SetParameter(keyValueList); +} + +int32_t WakeupIntellVoiceEngine::Release() +{ + INTELL_VOICE_LOG_INFO("enter"); + if (engine_ == nullptr) { + INTELL_VOICE_LOG_ERROR("engine is null"); + return -1; + } + + return engine_->Detach(); +} + +int32_t WakeupIntellVoiceEngine::SetCallback(shared_ptr callback) +{ + INTELL_VOICE_LOG_INFO("enter"); + if (engine_ == nullptr) { + INTELL_VOICE_LOG_ERROR("engine is null"); + return -1; + } + + callback_ = sptr(new (std::nothrow) EngineCallbackInner()); + if (callback_ == nullptr) { + INTELL_VOICE_LOG_ERROR("callback_ is nullptr"); + return -1; + } + callback_->SetEngineEventCallback(callback); + engine_->SetCallback(callback_->AsObject()); + return 0; +} +} +} \ No newline at end of file diff --git a/interfaces/inner_api/native/enroll_intell_voice_engine.h b/interfaces/inner_api/native/enroll_intell_voice_engine.h new file mode 100755 index 0000000..56c7666 --- /dev/null +++ b/interfaces/inner_api/native/enroll_intell_voice_engine.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ENROLL_INTELL_VOICE_ENGINE_H +#define ENROLL_INTELL_VOICE_ENGINE_H + +#include "i_intell_voice_engine.h" +#include "engine_callback_inner.h" +#include "intell_voice_info.h" + +namespace OHOS { +namespace IntellVoice { +using OHOS::IntellVoiceEngine::IIntellVoiceEngineEventCallback; +using OHOS::IntellVoiceEngine::IIntellVoiceEngine; +using OHOS::IntellVoiceEngine::EngineCallbackInner; + +struct EnrollIntelligentVoiceEngineDescriptor { + std::string wakeupPhrase; +}; + +struct EngineConfig { + std::string language; + std::string region; +}; + +class EnrollIntellVoiceEngine { +public: + EnrollIntellVoiceEngine(const EnrollIntelligentVoiceEngineDescriptor &descriptor); + ~EnrollIntellVoiceEngine(); + + int32_t Init(const EngineConfig &config); + int32_t Start(const bool &isLast); + int32_t Stop(); + int32_t Commit(); + int32_t SetSensibility(const int32_t &sensibility); + int32_t SetWakeupHapInfo(const WakeupHapInfo &info); + int32_t SetParameter(const std::string &key, const std::string &value); + int32_t GetParameter(const std::string &key); + int32_t Release(); + int32_t SetCallback(std::shared_ptr callback); + +private: + sptr engine_ = nullptr; + std::unique_ptr descriptor_ = nullptr; + sptr callback_ = nullptr; +}; +} // namespace IntellVoice +} // namespace OHOS + +#endif diff --git a/interfaces/inner_api/native/intell_voice_info.h b/interfaces/inner_api/native/intell_voice_info.h new file mode 100755 index 0000000..49badf2 --- /dev/null +++ b/interfaces/inner_api/native/intell_voice_info.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTELL_VOICE_UTILS_H +#define INTELL_VOICE_UTILS_H + +#include + +namespace OHOS { +namespace IntellVoice { +enum ServiceChangeType { + /* Service unavailable. */ + SERVICE_UNAVAILABLE = 0, +}; + +enum IntelligentVoiceEngineType { + /* Enroll engine. */ + ENROLL_ENGINE_TYPE = 0, + /* Wakeup engine. */ + WAKEUP_ENGINE_TYPE = 1, + /* Update engine. */ + UPDATE_ENGINE_TYPE = 2, +}; + +enum SensibilityType { + /* Low sensibility. */ + LOW_SENSIBILITY = 1, + /* Middle sensibility. */ + MIDDLE_SENSIBILITY = 2, + /* High sensibility. */ + HIGH_SENSIBILITY = 3, +}; + +enum EnrollIntelligentVoiceEventType { + /* Enroll None. */ + INTELLIGENT_VOICE_EVENT_ENROLL_NONE = 0, + /* Init done. */ + INTELLIGENT_VOICE_EVENT_ENROLL_INIT_DONE = 1, + /* Enroll complete. */ + INTELLIGENT_VOICE_EVENT_ENROLL_COMPLETE = 2, + /* Commit enroll complete. */ + INTELLIGENT_VOICE_EVENT_COMMIT_ENROLL_COMPLETE = 3, +}; + +enum WakeupIntelligentVoiceEventType { + /* Wakeup None. */ + INTELLIGENT_VOICE_EVENT_WAKEUP_NONE = 0, + /* Recognize complete. */ + INTELLIGENT_VOICE_EVENT_RECOGNIZE_COMPLETE = 1, +}; + +enum IntelligentVoiceErrorCode { + /* Success. */ + INTELLIGENT_VOICE_SUCCESS = 0, + /* Memory is insufficient. */ + INTELLIGENT_VOICE_NO_MEMORY = 22700101, + /* Invalid parameter. */ + INTELLIGENT_VOICE_INVALID_PARAM = 22700102, + /* Init failed. */ + INTELLIGENT_VOICE_INIT_FAILED = 22700103, + /* Enroll failed. */ + INTELLIGENT_VOICE_ENROLL_FAILED = 22700104, + /* Commit enroll failed. */ + INTELLIGENT_VOICE_COMMIT_ENROLL_FAILED = 22700105, + /* Recognize failed. */ + INTELLIGENT_VOICE_RECOGNIZE_FAILED = 22700106, +}; + +struct WakeupHapInfo { + std::string bundleName; + std::string abilityName; +}; +} // namespace IntellVoice +} // namespace OHOS +#endif diff --git a/interfaces/inner_api/native/intell_voice_manager.h b/interfaces/inner_api/native/intell_voice_manager.h new file mode 100755 index 0000000..b1f2818 --- /dev/null +++ b/interfaces/inner_api/native/intell_voice_manager.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTELL_VOICE_MANAGER_H +#define INTELL_VOICE_MANAGER_H + +#include "i_intell_voice_engine.h" + +namespace OHOS { +namespace IntellVoice { +using namespace std; +using namespace OHOS::IntellVoiceEngine; + +class IntellVoiceManager { +public: + static IntellVoiceManager *GetInstance(); + + int32_t CreateIntellVoiceEngine(IntellVoiceEngineType type, sptr &inst); + int32_t ReleaseIntellVoiceEngine(IntellVoiceEngineType type); + +private: + IntellVoiceManager(); + ~IntellVoiceManager(); + + void Init(); +}; +} // namespace IntellVoice +} // namespace OHOS + +#endif diff --git a/interfaces/inner_api/native/wakeup_intell_voice_engine.h b/interfaces/inner_api/native/wakeup_intell_voice_engine.h new file mode 100755 index 0000000..9b3a224 --- /dev/null +++ b/interfaces/inner_api/native/wakeup_intell_voice_engine.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef WAKEUP_INTELL_VOICE_ENGINE_H +#define WAKEUP_INTELL_VOICE_ENGINE_H + +#include "intell_voice_info.h" +#include "i_intell_voice_engine.h" +#include "engine_callback_inner.h" + +namespace OHOS { +namespace IntellVoice { +using OHOS::IntellVoiceEngine::IIntellVoiceEngineEventCallback; +using OHOS::IntellVoiceEngine::IIntellVoiceEngine; +using OHOS::IntellVoiceEngine::EngineCallbackInner; + +struct WakeupIntelligentVoiceEngineDescriptor { + bool needApAlgEngine; + std::string wakeupPhrase; +}; + +class WakeupIntellVoiceEngine { +public: + WakeupIntellVoiceEngine(const WakeupIntelligentVoiceEngineDescriptor &descriptor); + ~WakeupIntellVoiceEngine(); + + int32_t SetSensibility(const int32_t &sensibility); + int32_t SetWakeupHapInfo(const WakeupHapInfo &info); + int32_t SetParameter(const std::string &key, const std::string &value); + int32_t GetParameter(const std::string &key); + int32_t Release(); + int32_t SetCallback(std::shared_ptr callback); + +private: + sptr engine_ = nullptr; + std::unique_ptr descriptor_ = nullptr; + sptr callback_ = nullptr; +}; +} // namespace IntellVoice +} // namespace OHOS + +#endif diff --git a/interfaces/kits/js/@ohos.ai.intelligentVoice.d.ts b/interfaces/kits/js/@ohos.ai.intelligentVoice.d.ts new file mode 100755 index 0000000..e869113 --- /dev/null +++ b/interfaces/kits/js/@ohos.ai.intelligentVoice.d.ts @@ -0,0 +1,823 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AsyncCallback, Callback } from './@ohos.base'; + +/** + * @namespace intelligentVoice + * @since 10 + */ +declare namespace intelligentVoice { + /** + * Obtains an {@link IntelligentVoiceManager} instance. + * @permission ohos.permission.MANAGER_INTELLIGENT_VOICE + * @returns { IntelligentVoiceManager } this {@link IntelligentVoiceManager} object. + * @throws { BusinessError } 201 - Permission denied. + * @throws { BusinessError } 22700101 - No memory. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + function getIntelligentVoiceManager(): IntelligentVoiceManager; + + /** + * Implements intelligent voice management. + * @typedef IntelligentVoiceManager + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + interface IntelligentVoiceManager { + /** + * Obtains capability information. + * @permission ohos.permission.MANAGER_INTELLIGENT_VOICE + * @returns { Array } array of supported IntelligentVoiceEngineType. + * @throws { BusinessError } 201 - Permission denied. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + getCapabilityInfo(): Array; + /** + * Subscribes service change events. When the state of intelligent voice service changes, + * the callback is invoked. + * @permission ohos.permission.MANAGER_INTELLIGENT_VOICE + * @param { string } type - Type of the event to listen for. Only the serviceChange event is supported. + * @param { CallbackCallback } callback - Callback is invoked when the event is triggered. + * @throws { BusinessError } 201 - Permission denied. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + on(type: 'serviceChange', callback: Callback): void; + /** + * Unsubscribes service change events. + * @permission ohos.permission.MANAGER_INTELLIGENT_VOICE + * @param { string } type - Type of the event to listen for. Only the serviceChange event is supported. + * @throws { BusinessError } 201 - Permission denied. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + off(type: 'serviceChange'): void; + } + + /** + * Enumerates service change type. + * @enum {number} + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + enum ServiceChangeType { + /** + * Service unavailable. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + SERVICE_UNAVAILABLE = 0, + } + + /** + * Enumerates intelligent voice engine type. + * @enum {number} + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + enum IntelligentVoiceEngineType { + /** + * Enroll engine. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + ENROLL_ENGINE_TYPE = 0, + /** + * Wakeup engine. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + WAKEUP_ENGINE_TYPE = 1, + /** + * Update engine. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + UPDATE_ENGINE_TYPE = 2, + } + + /** + * Describes enroll intelligent voice engine. + * @typedef EnrollIntelligentVoiceEngineDescriptor + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + interface EnrollIntelligentVoiceEngineDescriptor { + /** + * Wakeup phrase. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + wakeupPhrase: string; + } + + /** + * Describes wakeup intelligent voice engine. + * @typedef WakeupIntelligentVoiceEngineDescriptor + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + interface WakeupIntelligentVoiceEngineDescriptor { + /** + * Need ap algorithm engine. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + needApAlgEngine: boolean; + /** + * Wakeup phrase. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + wakeupPhrase: string; + } + + /** + * Obtains an {@link EnrollIntelligentVoiceEngine} instance. This method uses an asynchronous callback to return the EnrollIntelligentVoiceEngine instance. + * @permission ohos.permission.MANAGER_INTELLIGENT_VOICE + * @param { EnrollIntelligentVoiceEngineDescriptor } descriptor - descriptor indicates enroll intelligent voice engine descriptor. + * @param { AsyncCallback } callback - the callback used to return the EnrollIntelligentVoiceEngine instance. + * @throws { BusinessError } 201 - Permission denied. + * @throws { BusinessError } 401 - if input parameter type or number mismatch. + * @throws { BusinessError } 22700101 - No memory. + * @throws { BusinessError } 22700102 - if input parameter value error. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + function createEnrollIntelligentVoiceEngine(descriptor: EnrollIntelligentVoiceEngineDescriptor, callback: AsyncCallback): void; + + /** + * Obtains an {@link EnrollIntelligentVoiceEngine} instance. This method uses a promise to return the EnrollIntelligentVoiceEngine instance. + * @permission ohos.permission.MANAGER_INTELLIGENT_VOICE + * @param { EnrollIntelligentVoiceEngineDescriptor } descriptor - descriptor indicates enroll intelligent voice engine descriptor. + * @returns { Promise; } the promise used to return the EnrollIntelligentVoiceEngine instance. + * @throws { BusinessError } 201 - Permission denied. + * @throws { BusinessError } 401 - if input parameter type or number mismatch. + * @throws { BusinessError } 22700101 - No memory. + * @throws { BusinessError } 22700102 - if input parameter value error. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + function createEnrollIntelligentVoiceEngine(descriptor: EnrollIntelligentVoiceEngineDescriptor): Promise; + + /** + * Obtains an {@link WakeupIntelligentVoiceEngine} instance. This method uses an asynchronous callback to return the WakeupIntelligentVoiceEngine instance. + * @permission ohos.permission.MANAGER_INTELLIGENT_VOICE + * @param { WakeupIntelligentVoiceEngineDescriptor } descriptor - descriptor indicates wakeup intelligent voice engine descriptor. + * @param { AsyncCallback } callback - the callback used to return the WakeupIntelligentVoiceEngine instance. + * @throws { BusinessError } 201 - Permission denied. + * @throws { BusinessError } 401 - if input parameter type or number mismatch. + * @throws { BusinessError } 22700101 - No memory. + * @throws { BusinessError } 22700102 - if input parameter value error. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + function createWakeupIntelligentVoiceEngine(descriptor: WakeupIntelligentVoiceEngineDescriptor, callback: AsyncCallback): void; + + /** + * Obtains an {@link WakeupIntelligentVoiceEngine} instance. This method uses a promise to return the WakeupIntelligentVoiceEngine instance. + * @permission ohos.permission.MANAGER_INTELLIGENT_VOICE + * @param { WakeupIntelligentVoiceEngineDescriptor } descriptor - descriptor indicates wakeup intelligent voice engine descriptor. + * @returns { Promise } the promise used to return the WakeupIntelligentVoiceEngine instance. + * @throws { BusinessError } 201 - Permission denied. + * @throws { BusinessError } 401 - if input parameter type or number mismatch. + * @throws { BusinessError } 22700101 - No memory. + * @throws { BusinessError } 22700102 - if input parameter value error. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + function createWakeupIntelligentVoiceEngine(descriptor: WakeupIntelligentVoiceEngineDescriptor): Promise; + + /** + * Describes enroll engine config. + * @typedef EnrollEngineConfig + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + interface EnrollEngineConfig { + /** + * Language that enroll engine supports. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + language: string; + /** + * Region that enroll engine supports. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + region: string; + } + + /** + * Enumerates sensibility type. + * @enum {number} + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + enum SensibilityType { + /** + * Low sensibility. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + LOW_SENSIBILITY = 1, + /** + * Middle sensibility. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + MIDDLE_SENSIBILITY = 2, + /** + * High sensibility. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + HIGH_SENSIBILITY = 3, + } + + /** + * Describes wakeup hap information. + * @typedef WakeupHapInfo + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + interface WakeupHapInfo { + /** + * Bundle name. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + bundleName: string; + /** + * Ability name. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + abilityName: string; + } + + /** + * Enumerates enroll intelligent voice event type. + * @enum {number} + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + enum EnrollIntelligentVoiceEventType { + /** + * Enroll None. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + INTELLIGENT_VOICE_EVENT_ENROLL_NONE = 0, + /** + * Init done. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + INTELLIGENT_VOICE_EVENT_ENROLL_INIT_DONE = 1, + /** + * Enroll complete. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + INTELLIGENT_VOICE_EVENT_ENROLL_COMPLETE = 2, + /** + * Commit enroll complete. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + INTELLIGENT_VOICE_EVENT_COMMIT_ENROLL_COMPLETE = 3, + } + + /** + * Enumerates wakeup intelligent voice event type. + * @enum {number} + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + enum WakeupIntelligentVoiceEventType { + /** + * Wakeup None. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + INTELLIGENT_VOICE_EVENT_WAKEUP_NONE = 0, + /** + * Recognize complete. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + INTELLIGENT_VOICE_EVENT_RECOGNIZE_COMPLETE = 1, + } + + /** + * Enumerates intelligent voice error code. + * @enum {number} + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + enum IntelligentVoiceErrorCode { + /** + * Success. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + INTELLIGENT_VOICE_SUCCESS = 0, + /** + * Memory is insufficient. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + INTELLIGENT_VOICE_NO_MEMORY = 22700101, + /** + * Invalid parameter. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + INTELLIGENT_VOICE_INVALID_PARAM = 22700102, + /** + * Init failed. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + INTELLIGENT_VOICE_INIT_FAILED = 22700103, + /** + * Enroll failed. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + INTELLIGENT_VOICE_ENROLL_FAILED = 22700104, + /** + * Commit enroll failed. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + INTELLIGENT_VOICE_COMMIT_ENROLL_FAILED = 22700105, + /** + * Recognize failed. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + INTELLIGENT_VOICE_RECOGNIZE_FAILED = 22700106, + } + + /** + * Describes enrol intelligent voice engine callback information. + * @typedef EnrollIntelligentVoiceEngineCallbackInfo + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + interface EnrollIntelligentVoiceEngineCallbackInfo { + /** + * Enroll event id. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + eventId: EnrollIntelligentVoiceEventType; + /** + * Error code. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + errCode: IntelligentVoiceErrorCode; + /** + * Describes enroll event context. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + context: string; + } + + /** + * Describes wakeup intelligent voice engine callback information. + * @typedef WakeupIntelligentVoiceEngineCallbackInfo + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + interface WakeupIntelligentVoiceEngineCallbackInfo { + /** + * Wakeup event id. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + eventId: WakeupIntelligentVoiceEventType; + /** + * Error code. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + errCode: IntelligentVoiceErrorCode; + /** + * Describes wakeup event context. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + context: string; + } + + /** + * Implements enroll intelligent voice engine. + * @typedef EnrollIntelligentVoiceEngine + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + interface EnrollIntelligentVoiceEngine { + /** + * Obtains the supported regions, This method uses an asynchronous callback to return the query result. + * @permission ohos.permission.MANAGER_INTELLIGENT_VOICE + * @param { AsyncCallback> } callback - the callback used to return the supported regions. + * @throws { BusinessError } 201 - Permission denied. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + getSupportedRegions(callback: AsyncCallback>): void; + /** + * Obtains the supported regions, This method uses a promise to return the query result. + * @permission ohos.permission.MANAGER_INTELLIGENT_VOICE + * @returns { Promise> } the promise used to return the supported regions. + * @throws { BusinessError } 201 - Permission denied. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + getSupportedRegions(): Promise>; + /** + * Initials the engine, This method uses an asynchronous callback to return the result. + * @permission ohos.permission.MANAGER_INTELLIGENT_VOICE + * @param { EnrollEngineConfig } config - config indicates enroll engine configuration. + * @param { AsyncCallback } callback - the callback used to return the result. + * @throws { BusinessError } 201 - Permission denied. + * @throws { BusinessError } 401 - if input parameter type or number mismatch. + * @throws { BusinessError } 22700102 - if input parameter value error. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + init(config: EnrollEngineConfig, callback: AsyncCallback): void; + /** + * Initials the engine, This method uses a promise to return the result. + * @permission ohos.permission.MANAGER_INTELLIGENT_VOICE + * @param { EnrollEngineConfig } config - config indicates enroll engine configuration. + * @returns { Promise } the promise used to return the result. + * @throws { BusinessError } 201 - Permission denied. + * @throws { BusinessError } 401 - if input parameter type or number mismatch. + * @throws { BusinessError } 22700102 - if input parameter value error. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + init(config: EnrollEngineConfig): Promise; + /** + * Starts the engine, This method uses an asynchronous callback to return the result. + * @permission ohos.permission.MANAGER_INTELLIGENT_VOICE + * @param { boolean } isLast - isLast indicates if it is the last time to start. + * @param { AsyncCallback } callback - the callback used to return the result. + * @throws { BusinessError } 201 - Permission denied. + * @throws { BusinessError } 401 - if input parameter type or number mismatch. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + start(isLast: boolean, callback: AsyncCallback): void; + /** + * Starts the engine, This method uses a promise to return the result. + * @permission ohos.permission.MANAGER_INTELLIGENT_VOICE + * @param { boolean } isLast - isLast indicates if it is the last time to start. + * @returns { Promise } the promise used to return the result. + * @throws { BusinessError } 201 - Permission denied. + * @throws { BusinessError } 401 - if input parameter type or number mismatch. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + start(isLast: boolean): Promise; + /** + * Stops the engine, This method uses an asynchronous callback to return the result. + * @permission ohos.permission.MANAGER_INTELLIGENT_VOICE + * @param { AsyncCallback } callback - the callback used to return the result. + * @throws { BusinessError } 201 - Permission denied. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + stop(callback: AsyncCallback): void; + /** + * Stops the engine, This method uses a promise to return the result. + * @permission ohos.permission.MANAGER_INTELLIGENT_VOICE + * @returns { Promise } the promise used to return the result. + * @throws { BusinessError } 201 - Permission denied. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + stop(): Promise; + /** + * commit enroll, This method uses an asynchronous callback to return the result. + * @permission ohos.permission.MANAGER_INTELLIGENT_VOICE + * @param { AsyncCallback } callback - the callback used to return the result. + * @throws { BusinessError } 201 - Permission denied. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + commit(callback: AsyncCallback): void; + /** + * commit enroll, This method uses a promise to return the result. + * @permission ohos.permission.MANAGER_INTELLIGENT_VOICE + * @returns { Promise } the promise used to return the result. + * @throws { BusinessError } 201 - Permission denied. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + commit(): Promise; + /** + * Sets wakeup hap information, This method uses an asynchronous callback to return the result. + * @permission ohos.permission.MANAGER_INTELLIGENT_VOICE + * @param { WakeupHapInfo } info - info indicates wakeup hap information. + * @param { AsyncCallback } callback - the callback used to return the result. + * @throws { BusinessError } 201 - Permission denied. + * @throws { BusinessError } 401 - if input parameter type or number mismatch. + * @throws { BusinessError } 22700102 - if input parameter value error. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + setWakeupHapInfo(info: WakeupHapInfo, callback: AsyncCallback): void; + /** + * Sets wakeup hap information, This method uses a promise to return the result. + * @permission ohos.permission.MANAGER_INTELLIGENT_VOICE + * @param { WakeupHapInfo } info - info indicates wakeup hap information. + * @returns { Promise } the promise used to return the result. + * @throws { BusinessError } 201 - Permission denied. + * @throws { BusinessError } 401 - if input parameter type or number mismatch. + * @throws { BusinessError } 22700102 - if input parameter value error. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + setWakeupHapInfo(info: WakeupHapInfo): Promise; + /** + * Sets sensibility, This method uses an asynchronous callback to return the result. + * @permission ohos.permission.MANAGER_INTELLIGENT_VOICE + * @param { SensibilityType } sensibility - sensibility to set. + * @param { AsyncCallback } callback - the callback used to return the result. + * @throws { BusinessError } 201 - Permission denied. + * @throws { BusinessError } 401 - if input parameter type or number mismatch. + * @throws { BusinessError } 22700102 - if input parameter value error. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + setSensibility(sensibility: SensibilityType, callback: AsyncCallback): void; + /** + * Sets sensibility, This method uses a promise to return the result. + * @permission ohos.permission.MANAGER_INTELLIGENT_VOICE + * @param { SensibilityType } sensibility - sensibility to set. + * @returns { Promise } the promise used to return the result. + * @throws { BusinessError } 201 - Permission denied. + * @throws { BusinessError } 401 - if input parameter type or number mismatch. + * @throws { BusinessError } 22700102 - if input parameter value error. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + setSensibility(sensibility: SensibilityType): Promise; + /** + * Sets an intelligent voice parameter. This method uses an asynchronous callback to return the result. + * @permission ohos.permission.MANAGER_INTELLIGENT_VOICE + * @param { string } key - the key of the intelligent voice parameter to set. + * @param { string } value - the value of the intelligent voice parameter to set. + * @param { AsyncCallback } callback - the callback used to return the result. + * @throws { BusinessError } 201 - Permission denied. + * @throws { BusinessError } 401 - if input parameter type or number mismatch. + * @throws { BusinessError } 22700102 - if input parameter value error. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + setParameter(key: string, value: string, callback: AsyncCallback): void; + /** + * Sets an intelligent voice parameter. This method uses a promise to return the result. + * @permission ohos.permission.MANAGER_INTELLIGENT_VOICE + * @param { string } key - the key of the intelligent voice parameter to set. + * @param { string } value - the value of the intelligent voice parameter to set. + * @returns { Promise } the promise used to return the result. + * @throws { BusinessError } 201 - Permission denied. + * @throws { BusinessError } 401 - if input parameter type or number mismatch. + * @throws { BusinessError } 22700102 - if input parameter value error. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + setParameter(key: string, value: string): Promise; + /** + * Obtains the value of an intelligent voice parameter. This method uses an asynchronous callback to return the query result. + * @permission ohos.permission.MANAGER_INTELLIGENT_VOICE + * @param { string } key - the key of the intelligent voice parameter whose value is to be obtained. + * @param { AsyncCallback } callback - the callback used to return the value of the intelligent voice parameter. + * @throws { BusinessError } 201 - Permission denied. + * @throws { BusinessError } 401 - if input parameter type or number mismatch. + * @throws { BusinessError } 22700102 - if input parameter value error. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + getParameter(key: string, callback: AsyncCallback): void; + /** + * Obtains the value of an intelligent voice parameter. This method uses an asynchronous callback to return the query result. + * @permission ohos.permission.MANAGER_INTELLIGENT_VOICE + * @param { string } key - the key of the intelligent voice parameter whose value is to be obtained. + * @returns { Promise } the promise used to return the value of the intelligent voice parameter. + * @throws { BusinessError } 201 - Permission denied. + * @throws { BusinessError } 401 - if input parameter type or number mismatch. + * @throws { BusinessError } 22700102 - if input parameter value error. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + getParameter(key: string): Promise; + /** + * Releases the engine, This method uses an asynchronous callback to return the result. + * @permission ohos.permission.MANAGER_INTELLIGENT_VOICE + * @param { AsyncCallback } callback - the callback used to return the result. + * @throws { BusinessError } 201 - Permission denied. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + release(callback: AsyncCallback): void; + /** + * Releases the engine, This method uses a promise to return the result. + * @permission ohos.permission.MANAGER_INTELLIGENT_VOICE + * @returns { Promise } the promise used to return the result. + * @throws { BusinessError } 201 - Permission denied. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + release(): Promise; + } + + /** + * Implements wakeup intelligent voice engine. + * @typedef WakeupIntelligentVoiceEngine + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + interface WakeupIntelligentVoiceEngine { + /** + * Obtains the supported regions, This method uses an asynchronous callback to return the query result. + * @permission ohos.permission.MANAGER_INTELLIGENT_VOICE + * @param { AsyncCallback> } callback - the callback used to return the supported regions. + * @throws { BusinessError } 201 - Permission denied. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + getSupportedRegions(callback: AsyncCallback>): void; + /** + * Obtains the supported regions, This method uses a promise to return the query result. + * @permission ohos.permission.MANAGER_INTELLIGENT_VOICE + * @returns { Promise> } the promise used to return the supported regions. + * @throws { BusinessError } 201 - Permission denied. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + getSupportedRegions(): Promise>; + /** + * Sets wakeup hap information, This method uses an asynchronous callback to return the result. + * @permission ohos.permission.MANAGER_INTELLIGENT_VOICE + * @param { WakeupHapInfo } info - info indicates wakeup hap information. + * @param { AsyncCallback } callback - the callback used to return the result. + * @throws { BusinessError } 201 - Permission denied. + * @throws { BusinessError } 401 - if input parameter type or number mismatch. + * @throws { BusinessError } 22700102 - if input parameter value error. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + setWakeupHapInfo(info: WakeupHapInfo, callback: AsyncCallback): void; + /** + * Sets wakeup hap information, This method uses a promise to return the result. + * @permission ohos.permission.MANAGER_INTELLIGENT_VOICE + * @param { WakeupHapInfo } info - info indicates wakeup hap information. + * @returns { Promise } the promise used to return the result. + * @throws { BusinessError } 201 - Permission denied. + * @throws { BusinessError } 401 - if input parameter type or number mismatch. + * @throws { BusinessError } 22700102 - if input parameter value error. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + setWakeupHapInfo(info: WakeupHapInfo): Promise; + /** + * Sets sensibility, This method uses an asynchronous callback to return the result. + * @permission ohos.permission.MANAGER_INTELLIGENT_VOICE + * @param { SensibilityType } sensibility - sensibility to set. + * @param { AsyncCallback } callback - the callback used to return the result. + * @throws { BusinessError } 201 - Permission denied. + * @throws { BusinessError } 401 - if input parameter type or number mismatch. + * @throws { BusinessError } 22700102 - if input parameter value error. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + setSensibility(sensibility: SensibilityType, callback: AsyncCallback): void; + /** + * Sets sensibility, This method uses a promise to return the result. + * @permission ohos.permission.MANAGER_INTELLIGENT_VOICE + * @param { SensibilityType } sensibility - sensibility to set. + * @returns { Promise } the promise used to return the result. + * @throws { BusinessError } 201 - Permission denied. + * @throws { BusinessError } 401 - if input parameter type or number mismatch. + * @throws { BusinessError } 22700102 - if input parameter value error. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + setSensibility(sensibility: SensibilityType): Promise; + /** + * Sets an intelligent voice parameter. This method uses an asynchronous callback to return the result. + * @permission ohos.permission.MANAGER_INTELLIGENT_VOICE + * @param { string } key - the key of the intelligent voice parameter to set. + * @param { string } value - the value of the intelligent voice parameter to set. + * @param { AsyncCallback } callback - the callback used to return the result. + * @throws { BusinessError } 201 - Permission denied. + * @throws { BusinessError } 401 - if input parameter type or number mismatch. + * @throws { BusinessError } 22700102 - if input parameter value error. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + setParameter(key: string, value: string, callback: AsyncCallback): void; + /** + * Sets an intelligent voice parameter. This method uses a promise to return the result. + * @permission ohos.permission.MANAGER_INTELLIGENT_VOICE + * @param { string } key - the key of the intelligent voice parameter to set. + * @param { string } value - the value of the intelligent voice parameter to set. + * @returns { Promise } the promise used to return the result. + * @throws { BusinessError } 201 - Permission denied. + * @throws { BusinessError } 401 - if input parameter type or number mismatch. + * @throws { BusinessError } 22700102 - if input parameter value error. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + setParameter(key: string, value: string): Promise; + /** + * Obtains the value of an intelligent voice parameter. This method uses an asynchronous callback to return the query result. + * @permission ohos.permission.MANAGER_INTELLIGENT_VOICE + * @param { string } key - the key of the intelligent voice parameter whose value is to be obtained. + * @param { AsyncCallback } callback - the callback used to return the value of the intelligent voice parameter. + * @throws { BusinessError } 201 - Permission denied. + * @throws { BusinessError } 401 - if input parameter type or number mismatch. + * @throws { BusinessError } 22700102 - if input parameter value error. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + getParameter(key: string, callback: AsyncCallback): void; + /** + * Obtains the value of an intelligent voice parameter. This method uses an asynchronous callback to return the query result. + * @permission ohos.permission.MANAGER_INTELLIGENT_VOICE + * @param { string } key - the key of the intelligent voice parameter whose value is to be obtained. + * @returns { Promise } the promise used to return the value of the intelligent voice parameter. + * @throws { BusinessError } 201 - Permission denied. + * @throws { BusinessError } 401 - if input parameter type or number mismatch. + * @throws { BusinessError } 22700102 - if input parameter value error. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + getParameter(key: string): Promise; + /** + * Releases the engine, This method uses an asynchronous callback to return the result. + * @permission ohos.permission.MANAGER_INTELLIGENT_VOICE + * @param { AsyncCallback } callback - the callback used to return the result. + * @throws { BusinessError } 201 - Permission denied. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + release(callback: AsyncCallback): void; + /** + * Releases the engine, This method uses a promise to return the result. + * @permission ohos.permission.MANAGER_INTELLIGENT_VOICE + * @returns { Promise } the promise used to return the result. + * @throws { BusinessError } 201 - Permission denied. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + release(): Promise; + /** + * Subscribes wakeup intelligent voice events. When wakeup intelligent voice events reach, + * the callback is invoked. + * @permission ohos.permission.MANAGER_INTELLIGENT_VOICE + * @param { string } type - Type of the event to listen for. Only the wakeupIntelligentVoice event is supported. + * @param { Callback } callback - the callback invoked when the event is triggered. + * @throws { BusinessError } 201 - Permission denied. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + on(type: 'wakeupIntelligentVoiceEvent', callback: Callback): void; + /** + * Unsubscribes wakeup intelligent voice events. + * @permission ohos.permission.MANAGER_INTELLIGENT_VOICE + * @param { string } type - Type of the event to listen for. Only the wakeupIntelligentVoice event is supported. + * @throws { BusinessError } 201 - Permission denied. + * @syscap SystemCapability.AI.IntelligentVoice.Core + * @since 10 + */ + off(type: 'wakeupIntelligentVoiceEvent'); + } +} + +export default intelligentVoice; \ No newline at end of file diff --git a/llt/hdt/CMakeLists.txt b/llt/hdt/CMakeLists.txt new file mode 100755 index 0000000..0736247 --- /dev/null +++ b/llt/hdt/CMakeLists.txt @@ -0,0 +1,64 @@ +# Copyright (c) 2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +cmake_minimum_required(VERSION 3.13) + +project(hdt VERSION 1.0 LANGUAGES C CXX) + +# Library file compilation +add_subdirectory(depend_libs/cmake) + +# COMPONENT CMAKE +include("${CMAKE_CURRENT_SOURCE_DIR}/conf/comp.cmake") + +# PATH +set(ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../) +set(CLANG_DIR ${ROOT_DIR}prebuilts/clang/host/linux-x86/clang-r353983c/) + +# COMPILE_OPTIONS +set(CMAKE_CXX_COMPILER "${CLANG_DIR}/bin/clang++") +set(CMAKE_C_COMPILER "${CLANG_DIR}/bin/clang") +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99") + +# INCLUDE_DIR +add_compile_options(-include memory) +include("${CMAKE_CURRENT_SOURCE_DIR}/conf/include.cmake") +include_directories(${INCLUDE_DIRECTORIES}) + + +# TEST_SOURCE_FILES +aux_source_directory(${TEST_SRC_DIR}/src/ TEST_SRC) +aux_source_directory(${TEST_SRC_DIR}/src/statemgr TEST_SRC) + + +# TEST_CASE_FILES +aux_source_directory(testcase/intell_voice_utils TEST_CASE) + +# STUB_FILE +aux_source_directory(stub STUB_FILE) + +# TARGET +add_executable(intellvoicetest ${TEST_SRC} ${TEST_CASE} ${STUB_FILE} ${DEPEND_SRC}) + +add_dependencies(intellvoicetest hilog sec utilsbase) +target_link_libraries(intellvoicetest hilog sec utilsbase) + +# MESSAGE +get_target_property(COMPILE_FLAGS intellvoicetest COMPILE_OPTIONS) +get_target_property(LINK_FLAGS intellvoicetest LINK_OPTIONS) +message(STATUS "Compiler id: ${CMAKE_CXX_COMPILER_ID}") +message(STATUS "Compile flags: ${COMPILE_FLAGS}") +message(STATUS "Link flags: ${LINK_FLAGS}") +message(STATUS "Build Type: ${CMAKE_BUILD_TYPE}") \ No newline at end of file diff --git a/llt/hdt/build.sh b/llt/hdt/build.sh new file mode 100755 index 0000000..bf01ede --- /dev/null +++ b/llt/hdt/build.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# Copyright (c) 2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -e + +CUR_DIR=$(dirname $(readlink -f $0)) +ROOT_DIR=${CUR_DIR}/../../../../../ +CLANG_DIR=${ROOT_DIR}prebuilts/clang/host/linux-x86/clang-r353983c/bin + +export PATH=$PATH:${CLANG_DIR} + +hdt comp -i --compiler clang9.0.3 +hdt build -s on -c on \ No newline at end of file diff --git a/llt/hdt/depend_libs/cmake/CMakeLists.txt b/llt/hdt/depend_libs/cmake/CMakeLists.txt new file mode 100755 index 0000000..f109e99 --- /dev/null +++ b/llt/hdt/depend_libs/cmake/CMakeLists.txt @@ -0,0 +1,23 @@ +cmake_minimum_required(VERSION 3.13) + +project(lib_cmake VERSION 1.0 LANGUAGES C CXX) + +# CMAKE_WITH_ALL_COMPONENTS + +# PATH +set(ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../../) +set(CLANG_DIR ${ROOT_DIR}prebuilts/clang/host/linux-x86/clang-r353983c/) +set(INTELL_VOICE_DIR ${ROOT_DIR}foundation/ai/intelligent_voice_framework/llt/hdt/) +set(LIB_PATH ${INTELL_VOICE_DIR}/build) + +# COMPILE_OPTIONS +set(CMAKE_CXX_COMPILER "${CLANG_DIR}/bin/clang++") +set(CMAKE_C_COMPILER "${CLANG_DIR}/bin/clang") +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99") +add_compile_options(-Wno-c++11-narrowing) + +include("libhilog.cmake") +include("libsec.cmake") +include("libutilsbase.cmake") \ No newline at end of file diff --git a/llt/hdt/depend_libs/cmake/libhilog.cmake b/llt/hdt/depend_libs/cmake/libhilog.cmake new file mode 100755 index 0000000..d18396c --- /dev/null +++ b/llt/hdt/depend_libs/cmake/libhilog.cmake @@ -0,0 +1,31 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved. +# Description: liblog.cmake +# Create: 2022-8-15 + +cmake_minimum_required(VERSION 3.13) +set(HILOG_DIR ${ROOT_DIR}base/hiviewdfx/hilog/) +set(HILOG_SRC_DIR ${ROOT_DIR}base/hiviewdfx/hilog/frameworks/libhilog/) + +include_directories(${ROOT_DIR}third_party/bounds_checking_function/include) +include_directories(${HILOG_DIR}frameworks/include/) +include_directories(${HILOG_DIR}frameworks/libhilog/include/) +include_directories(${HILOG_DIR}frameworks/libhilog/socket/include/) +include_directories(${HILOG_DIR}frameworks/libhilog/param/include/) +include_directories(${HILOG_DIR}frameworks/libhilog/utils/include/) +include_directories(${HILOG_DIR}frameworks/libhilog/vsnprintf/include/) +include_directories(${HILOG_DIR}interfaces/native/innerkits/include/) + +set(LIBRARY_OUTPUT_PATH ${LIB_PATH}) +set(MACRO_DEFINITION_LOG -D__LINUX__) + +# TEST_SOURCE_FILES +file(GLOB LOG_SRCS + ${HILOG_SRC_DIR}hilog.cpp + ${HILOG_SRC_DIR}hilog_printf.cpp + ${HILOG_SRC_DIR}utils/log_print.cpp + ${HILOG_SRC_DIR}utils/log_utils.cpp + ${HILOG_SRC_DIR}vsnprintf/vsnprintf_s_p.cpp) + +add_library(hilog STATIC ${LOG_SRCS}) +target_compile_definitions(hilog PRIVATE ${MACRO_DEFINITION_LOG}) +set_target_properties(hilog PROPERTIES COMPILE_FLAGS "-w") \ No newline at end of file diff --git a/llt/hdt/depend_libs/cmake/libsec.cmake b/llt/hdt/depend_libs/cmake/libsec.cmake new file mode 100755 index 0000000..492cee5 --- /dev/null +++ b/llt/hdt/depend_libs/cmake/libsec.cmake @@ -0,0 +1,27 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved. +# Description: liblog.cmake +# Create: 2022-8-15 + +cmake_minimum_required(VERSION 3.13) +set(SEC_DIR ${ROOT_DIR}third_party/bounds_checking_function/) + +include_directories(${SEC_DIR}include) + +set(LIBRARY_OUTPUT_PATH ${LIB_PATH}) + +set(MACRO_DEFINITION_LOG + -D__LINUX__ + -D_INC_STRING_S + -D_INC_WCHAR_S + -D_SECIMP=// + -D_STDIO_S_DEFINED + -D_INC_STDIO_S + -D_INC_STDLIB_S + -D_INC_MEMORY_S) + +# TEST_SOURCE_FILES +aux_source_directory(${SEC_DIR}/src SEC_SRCS) + +add_library(sec STATIC ${SEC_SRCS}) +target_compile_definitions(sec PRIVATE ${MACRO_DEFINITION_LOG}) +set_target_properties(sec PROPERTIES COMPILE_FLAGS "-w") \ No newline at end of file diff --git a/llt/hdt/depend_libs/cmake/libutilsbase.cmake b/llt/hdt/depend_libs/cmake/libutilsbase.cmake new file mode 100755 index 0000000..06ac54a --- /dev/null +++ b/llt/hdt/depend_libs/cmake/libutilsbase.cmake @@ -0,0 +1,24 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved. +# Description: liblog.cmake +# Create: 2022-8-15 + +cmake_minimum_required(VERSION 3.13) +set(UTILSBASE_DIR ${ROOT_DIR}commonlibrary/c_utils/base/) + +include_directories(${UTILSBASE_DIR}include) +include_directories(${UTILSBASE_DIR}src) +include_directories(${ROOT_DIR}kernel/linux-5.10-lts/make_output/usr/include/) + +set(LIBRARY_OUTPUT_PATH ${LIB_PATH}) + +# TEST_SOURCE_FILES +aux_source_directory(${UTILSBASE_DIR}/src UTILSBASE_DIR_SRCS) + +file(GLOB SRC_BLACK_LIST + ${UTILSBASE_DIR}/src/file_ex.cpp) + +list(REMOVE_ITEM UTILSBASE_DIR_SRCS ${SRC_BLACK_LIST}) + +add_library(utilsbase STATIC ${UTILSBASE_DIR_SRCS}) +target_compile_options(utilsbase PRIVATE -include functional -includelimits.h) +set_target_properties(utilsbase PROPERTIES COMPILE_FLAGS "-w") \ No newline at end of file diff --git a/llt/hdt/depend_libs/src/file_ex.cpp b/llt/hdt/depend_libs/src/file_ex.cpp new file mode 100755 index 0000000..65b469c --- /dev/null +++ b/llt/hdt/depend_libs/src/file_ex.cpp @@ -0,0 +1,346 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "file_ex.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "directory_ex.h" +#include "utils_log.h" + +using namespace std; + +const int MAX_FILE_LENGTH = 32 * 1024 * 1024; + +namespace OHOS { +bool LoadStringFromFile(const string& filePath, string& content) +{ + ifstream file(filePath.c_str()); + if (!file.is_open()) { + UTILS_LOGD("open file failed! filePath:%{public}s", filePath.c_str()); + return false; + } + + file.seekg(0, ios::end); + const long fileLength = file.tellg(); + if (fileLength > MAX_FILE_LENGTH) { + UTILS_LOGD("invalid file length(%{public}ld)!", fileLength); + return false; + } + + content.clear(); + file.seekg(0, ios::beg); + copy(istreambuf_iterator(file), istreambuf_iterator(), back_inserter(content)); + return true; +} + +string GetFileNameByFd(const int fd) +{ + if (fd <= 0) { + return string(); + } + + string fdPath = "/proc/self/fd/" + std::to_string(fd); + char fileName[PATH_MAX + 1] = {0}; + + int ret = readlink(fdPath.c_str(), fileName, PATH_MAX); + if (ret < 0 || ret > PATH_MAX) { + UTILS_LOGD("Get fileName failed, ret is: %{public}d!", ret); + return string(); + } + fileName[ret] = '\0'; + return string(fileName); +} + +bool LoadStringFromFdToFile(int fd, string& content) +{ + string fileName = GetFileNameByFd(fd); + if (fileName.empty()) { + UTILS_LOGD("LoadStringFromFd get file name by fd failed!"); + return false; + } + + if (!LoadStringFromFile(fileName, content)) { + UTILS_LOGE("LoadStringFromFd get string from file failed!"); + return false; + } + return true; +} + +bool LoadStringFromFd(int fd, string& content) +{ + if (fd <= 0) { + UTILS_LOGD("invalid fd:%{public}d", fd); + return false; + } + + const long fileLength = lseek(fd, 0, SEEK_END); + if (fileLength > MAX_FILE_LENGTH) { + UTILS_LOGE("invalid file length(%{public}ld)!", fileLength); + return false; + } + + // lseek is not support the linux file node + if (fileLength < 0) { + return LoadStringFromFdToFile(fd, content); + } + + if (fileLength == 0) { + return true; + } + + content.resize(fileLength); + int loc = lseek(fd, 0, SEEK_SET); + if (loc == -1) { + UTILS_LOGE("lseek file to begin failed!"); + return false; + } + + const long len = read(fd, content.data(), fileLength); + if (len != fileLength) { + UTILS_LOGE("the length read from file is not equal to fileLength!len:%{public}ld,fileLen:%{public}ld", + len, fileLength); + return false; + } + + return true; +} + +bool SaveStringToFile(const std::string& filePath, const std::string& content, bool truncated /* = true */) +{ + if (content.empty()) { + UTILS_LOGI("content is empty, no need to save!"); + return true; + } + + ofstream file; + if (truncated) { + file.open(filePath.c_str(), ios::out | ios::trunc); + } else { + file.open(filePath.c_str(), ios::out | ios::app); + } + + if (!file.is_open()) { + UTILS_LOGD("open file failed! filePath:%{private}s", filePath.c_str()); + return false; + } + + file.write(content.c_str(), content.length()); + if (file.fail()) { + UTILS_LOGE("write content to file failed!file:%{private}s, content:%{private}s", + filePath.c_str(), content.c_str()); + return false; + } + return true; +} + +bool SaveStringToFd(int fd, const std::string& content) +{ + if (fd <= 0) { + UTILS_LOGD("invalid fd:%{public}d", fd); + return false; + } + + if (content.empty()) { + UTILS_LOGI("content is empty, no need to save!"); + return true; + } + + const long len = write(fd, content.c_str(), content.length()); + if (len < 0) { + UTILS_LOGE("write file failed!errno:%{public}d, err:%{public}s", errno, strerror(errno)); + return false; + } + + if (static_cast(len) != content.length()) { + UTILS_LOGE("the length write to file is not equal to fileLength!len:%{public}ld, fileLen:%{public}zu", + len, content.length()); + return false; + } + + return true; +} + +bool LoadBufferFromNodeFile(const string& filePath, vector& content) +{ + string realPath; + if (!PathToRealPath(filePath, realPath)) { + UTILS_LOGD("filePath to realPath failed! filePath:%{private}s", filePath.c_str()); + return false; + } + + FILE *fp = fopen(realPath.c_str(), "r"); + if (fp == nullptr) { + UTILS_LOGD("open file failed! filePath:%{private}s", realPath.c_str()); + return false; + } + + int byteCount = 1; + while (!feof(fp)) { + if (byteCount > MAX_FILE_LENGTH) { + UTILS_LOGE("LoadBufferFromNodeFile invalid file length(%{public}d)!", byteCount); + fclose(fp); + fp = nullptr; + content.clear(); + return false; + } + char ch = fgetc(fp); + content.push_back(ch); + byteCount++; + } + + fclose(fp); + fp = nullptr; + return true; +} + +/* load file to buffer. If the buffer is not empty,then overwrite */ +bool LoadBufferFromFile(const string& filePath, vector& content) +{ + ifstream file; + file.open(filePath.c_str(), ios::in | ios::binary); + if (!file.is_open()) { + UTILS_LOGD("open file failed! filePath:%{private}s", filePath.c_str()); + return false; + } + + file.seekg(0, std::ios::end); + const long fileLength = file.tellg(); + if (fileLength > MAX_FILE_LENGTH) { + UTILS_LOGD("invalid file length(%{public}ld)!", fileLength); + return false; + } + + // lseek is not support the linux file node + if (fileLength < 0) { + return LoadBufferFromNodeFile(filePath, content); + } + + if (fileLength == 0) { + content.clear(); + return true; + } + + file.seekg(0, std::ios::beg); + if (file.fail()) { + UTILS_LOGE("seekg file to begin failed!filePath:%{private}s", filePath.c_str()); + return false; + } + + content.resize(fileLength); + file.read(&content[0], fileLength); + return true; +} + +bool SaveBufferToFile(const string& filePath, const vector& content, bool truncated /* = true */) +{ + if (content.empty()) { + UTILS_LOGI("content is empty, no need to save!"); + return true; + } + + // if the file is not exist,create it first! + ios_base::openmode mode = truncated ? (ios::out | ios::binary | ios::trunc) : (ios::out | ios::binary | ios::app); + ofstream file; + file.open(filePath.c_str(), mode); + if (!file.is_open()) { + UTILS_LOGD("open file failed! filePath:%{private}s, mode:%{private}d", filePath.c_str(), mode); + return false; + } + + file.write(&content[0], content.size()); + return true; +} + +bool FileExists(const string& fileName) +{ + return (access(fileName.c_str(), F_OK) == 0); +} + +bool StringExistsInFile(const string& fileName, const string& subStr, bool caseSensitive /* = true */) +{ + if (subStr.empty()) { + UTILS_LOGD("String is empty"); + return false; + } + + string str; + if (!LoadStringFromFile(fileName, str)) { + UTILS_LOGD("File load fail, filePath:%{private}s", fileName.c_str()); + return false; + } + + if (caseSensitive) { + return (str.find(subStr) != string::npos); + } + + string strlower(str); + string sublower(subStr); + transform(str.begin(), str.end(), strlower.begin(), ::tolower); + transform(subStr.begin(), subStr.end(), sublower.begin(), ::tolower); + return (strlower.find(sublower) != string::npos); +} + +int CountStrInStr(const string& str, const string& subStr) +{ + if (subStr.empty()) { + UTILS_LOGD("subStr is empty"); + return 0; + } + + size_t position = 0; + int count = 0; + size_t length = subStr.length(); + while ((position = str.find(subStr, position)) != string::npos) { + position += length; + count++; + } + + return count; +} + +int CountStrInFile(const string& fileName, const string& subStr, bool caseSensitive /* = true */) +{ + if (subStr.empty()) { + UTILS_LOGD("String is empty"); + return -1; + } + + string str; + if (!LoadStringFromFile(fileName, str)) { + UTILS_LOGD("File load fail, filePath:%{private}s", fileName.c_str()); + return -1; + } + + // If case-insensitive, strings are converted to lowercase. + if (caseSensitive) { + return CountStrInStr(str, subStr); + } + + string strlower(str); + string sublower(subStr); + transform(str.begin(), str.end(), strlower.begin(), ::tolower); + transform(subStr.begin(), subStr.end(), sublower.begin(), ::tolower); + return CountStrInStr(strlower, sublower); +} +} diff --git a/llt/hdt/run.sh b/llt/hdt/run.sh new file mode 100755 index 0000000..719a0c7 --- /dev/null +++ b/llt/hdt/run.sh @@ -0,0 +1,23 @@ +#!/bin/bash +# Copyright (c) 2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -e + +CUR_DIR=$(dirname $(readlink -f $0)) +CUR_DIR=$(cd ${CUR_DIR}; pwd) +ROOT_DIR=${CUR_DIR}/../../../../../ +ROOT_DIR=$(cd ${ROOT_DIR}; pwd) + +hdt run +hdt report --args='--filter='${TESTING_SRC_DIR}' --gcov-executable "'${ROOT_DIR}/'prebuilts/clang/host/linux-x86/clang-r353983c/bin/llvm-cov gcov"' \ No newline at end of file diff --git a/llt/hdt/stub/message_parcel.cpp b/llt/hdt/stub/message_parcel.cpp new file mode 100755 index 0000000..4406310 --- /dev/null +++ b/llt/hdt/stub/message_parcel.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "message_parcel.h" + +namespace OHOS { +bool WriteFileDescriptor(int fd) +{ + (void)fd; + return false; +} + +int ReadFileDescriptor() +{ + return 0; +} +} // namespace OHOS diff --git a/llt/hdt/testcase/intell_voice_utils/test_time_util.cpp b/llt/hdt/testcase/intell_voice_utils/test_time_util.cpp new file mode 100755 index 0000000..8f88ef2 --- /dev/null +++ b/llt/hdt/testcase/intell_voice_utils/test_time_util.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define CATCH_CONFIG_MAIN +#include "catch2/catch.hpp" + +#include "time_util.h" + +namespace OHOS { +namespace IntellVoiceUtils { +TEST_CASE("GetCurrTime", "intell_voice_time") { + enum TimeFormat format = TIME_FORMAT_DEFAULT; + std::string str = TimeUtil::GetCurrTime(format); + REQUIRE(str != ""); + + SECTION("continuous time format") { + TimeFormat format = TIME_FORMAT_CONTINOUS; + str = TimeUtil::GetCurrTime(format); + REQUIRE(str != ""); + } + SECTION("standard time format") { + TimeFormat format = TIME_FORMAT_STANDARD; + str = TimeUtil::GetCurrTime(format); + REQUIRE(str != ""); + } +} +} +} \ No newline at end of file diff --git a/sa_profile/2688.xml b/sa_profile/2688.xml new file mode 100755 index 0000000..b991862 --- /dev/null +++ b/sa_profile/2688.xml @@ -0,0 +1,25 @@ + + + + intell_voice_service + + 2688 + /system/lib64/libintell_voice_server.z.so + true + false + 1 + + \ No newline at end of file diff --git a/sa_profile/BUILD.gn b/sa_profile/BUILD.gn new file mode 100755 index 0000000..bc8f697 --- /dev/null +++ b/sa_profile/BUILD.gn @@ -0,0 +1,19 @@ +# Copyright (c) 2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos/sa_profile/sa_profile.gni") + +ohos_sa_profile("intell_voice_service_sa_profile") { + sources = [ "2688.xml" ] + part_name = "intelligent_voice_framework" +} diff --git a/services/BUILD.gn b/services/BUILD.gn new file mode 100755 index 0000000..29029a8 --- /dev/null +++ b/services/BUILD.gn @@ -0,0 +1,146 @@ +# Copyright (c) 2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") + +ohos_shared_library("intell_voice_proxy") { + sources = [ + "intell_voice_engine/proxy/engine_callback_inner.cpp", + "intell_voice_engine/proxy/intell_voice_engine_callback_stub.cpp", + "intell_voice_engine/proxy/intell_voice_engine_proxy.cpp", + "intell_voice_engine/proxy/intell_voice_service_proxy.cpp", + ] + + include_dirs = [ + "intell_voice_engine", + "intell_voice_engine/proxy", + "//foundation/ai/intelligent_voice_framework/utils", + ] + + cflags_cc = [ + "-Wno-error=unused-parameter", + "-DHILOG_ENABLE", + "-DENABLE_DEBUG", + ] + + public_deps = [ "//drivers/interface/intelligent_voice/engine/v1_0:intell_voice_engine_idl_headers" ] + + external_deps = [ + "c_utils:utils", + "hdf_core:libhdf_host", + "hdf_core:libhdf_ipc_adapter", + "hdf_core:libhdf_utils", + "hdf_core:libhdi", + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + "safwk:system_ability_fwk", + "samgr:samgr_proxy", + ] + + subsystem_name = "ai" + part_name = "intelligent_voice_framework" +} + +ohos_shared_library("intell_voice_server") { + configs = [ "//build/config/compiler:exceptions" ] + + sources = [ + "intell_voice_engine/server/base/adapter_callback_service.cpp", + "intell_voice_engine/server/base/audio_source.cpp", + "intell_voice_engine/server/base/engine_base.cpp", + "intell_voice_engine/server/base/engine_factory.cpp", + "intell_voice_engine/server/base/file_source.cpp", + "intell_voice_engine/server/enroll/enroll_adapter_listener.cpp", + "intell_voice_engine/server/enroll/enroll_engine.cpp", + "intell_voice_engine/server/sa/intell_voice_engine_callback_proxy.cpp", + "intell_voice_engine/server/sa/intell_voice_engine_stub.cpp", + "intell_voice_engine/server/sa/intell_voice_service.cpp", + "intell_voice_engine/server/sa/intell_voice_service_manager.cpp", + "intell_voice_engine/server/sa/intell_voice_service_stub.cpp", + "intell_voice_engine/server/utils/history_info_mgr.cpp", + "intell_voice_engine/server/utils/service_db_helper.cpp", + "intell_voice_engine/server/utils/switch_observer.cpp", + "intell_voice_engine/server/utils/switch_provider.cpp", + "intell_voice_engine/server/utils/system_event_observer.cpp", + "intell_voice_engine/server/wakeup/wakeup_adapter_listener.cpp", + "intell_voice_engine/server/wakeup/wakeup_engine.cpp", + "intell_voice_trigger/server/connector_mgr/trigger_callback_impl.cpp", + "intell_voice_trigger/server/connector_mgr/trigger_connector.cpp", + "intell_voice_trigger/server/connector_mgr/trigger_connector_internal_impl.cpp", + "intell_voice_trigger/server/connector_mgr/trigger_connector_internal_validation.cpp", + "intell_voice_trigger/server/connector_mgr/trigger_connector_mgr.cpp", + "intell_voice_trigger/server/trigger_base_type.cpp", + "intell_voice_trigger/server/trigger_db_helper.cpp", + "intell_voice_trigger/server/trigger_detector.cpp", + "intell_voice_trigger/server/trigger_detector_callback.cpp", + "intell_voice_trigger/server/trigger_detector_recognition_callback.cpp", + "intell_voice_trigger/server/trigger_helper.cpp", + "intell_voice_trigger/server/trigger_manager.cpp", + "intell_voice_trigger/server/trigger_service.cpp", + ] + + public_deps = [ + "//drivers/interface/intelligent_voice/engine/v1_0:intell_voice_engine_idl_headers", + "//drivers/interface/intelligent_voice/trigger/v1_0:intell_voice_trigger_idl_headers", + ] + + include_dirs = [ + "//foundation/multimedia/audio_framework/interfaces/inner_api/native/audiocommon/include", + "//foundation/multimedia/audio_framework/interfaces/inner_api/native/audiocapturer/include", + "//foundation/ai/intelligent_voice_framework/utils", + "intell_voice_engine", + "intell_voice_engine/server/base", + "intell_voice_engine/server/enroll", + "intell_voice_engine/server/sa", + "intell_voice_engine/server/utils", + "intell_voice_engine/server/wakeup", + "intell_voice_trigger/server", + "intell_voice_trigger/server/connector_mgr", + ] + + cflags_cc = [ + "-Wno-error=unused-parameter", + "-DHILOG_ENABLE", + "-DENABLE_DEBUG", + ] + + deps = [ + "//drivers/interface/intelligent_voice/engine/v1_0:libintell_voice_engine_proxy_1.0", + "//drivers/interface/intelligent_voice/trigger/v1_0:libintell_voice_trigger_proxy_1.0", + "//foundation/ability/ability_runtime/frameworks/native/appkit:app_context", + "//foundation/ability/ability_runtime/interfaces/inner_api/dataobs_manager:dataobs_manager", + "//foundation/ai/intelligent_voice_framework/utils:intell_voice_utils", + "//foundation/multimedia/audio_framework/frameworks/native/audiocapturer:audio_capturer", + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "ability_runtime:ability_manager", + "access_token:libaccesstoken_sdk", + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "data_share:datashare_consumer", + "eventhandler:libeventhandler", + "hdf_core:libhdi", + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + "kv_store:distributeddata_inner", + "relational_store:native_rdb", + "safwk:system_ability_fwk", + "samgr:samgr_proxy", + ] + + subsystem_name = "ai" + part_name = "intelligent_voice_framework" +} diff --git a/services/etc/BUILD.gn b/services/etc/BUILD.gn new file mode 100755 index 0000000..789d867 --- /dev/null +++ b/services/etc/BUILD.gn @@ -0,0 +1,21 @@ +# Copyright (c) 2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") + +ohos_prebuilt_etc("intell_voice_service.rc") { + source = "intell_voice_service.cfg" + relative_install_dir = "init" + subsystem_name = "ai" + part_name = "intelligent_voice_framework" +} diff --git a/services/etc/intell_voice_service.cfg b/services/etc/intell_voice_service.cfg new file mode 100755 index 0000000..59e3f29 --- /dev/null +++ b/services/etc/intell_voice_service.cfg @@ -0,0 +1,22 @@ +{ + "jobs" : [{ + "name" : "post-fs-data", + "cmds" : [ + "mkdir /data/service/el1/public/database 0711 ddms ddms", + "mkdir /data/service/el1/public/database/intell_voice_service_manager 02770 intell_voice ddms", + "mkdir /data/data/intell_voice 0760 intell_voice intell_voice", + "mkdir /data/data/intell_voice/pcm_data 0760 intell_voice intell_voice", + "start intell_voice_service" + ] + } + ], + "services" : [{ + "name" : "intell_voice_service", + "path" : ["/system/bin/sa_main", "/system/profile/intell_voice_service.xml"], + "uid" : "intell_voice", + "gid" : ["system","intell_voice"], + "permission" : ["ohos.permission.MANAGE_INTELLIGENT_VOICE"], + "disabled" : 1 + } + ] +} \ No newline at end of file diff --git a/services/etc/intell_voice_service.rc b/services/etc/intell_voice_service.rc new file mode 100755 index 0000000..5d6ca72 --- /dev/null +++ b/services/etc/intell_voice_service.rc @@ -0,0 +1,8 @@ +on post-fs-data + start intell_voice_service +service intell_voice_service /system/bin/sa_main /system/profile/intell_voice_service.xml + class z_core + user system + group system shell + seclabel u:r:intell_voice_service:s0 + onrestart restart intell_voice_hal_1_0 \ No newline at end of file diff --git a/services/intell_voice_engine/i_intell_voice_engine.h b/services/intell_voice_engine/i_intell_voice_engine.h new file mode 100755 index 0000000..68f39dc --- /dev/null +++ b/services/intell_voice_engine/i_intell_voice_engine.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IINTELL_VOICE_ENGINE_H +#define IINTELL_VOICE_ENGINE_H +#include "iremote_broker.h" +#include "i_intell_voice_engine_callback.h" + +namespace OHOS { +namespace IntellVoiceEngine { +enum IntellVoiceEngineType { + INTELL_VOICE_ENROLL = 0, + INTELL_VOICE_WAKEUP, + INTELL_VOICE_UPDATE, + ENGINE_TYPE_BUT +}; + +struct IntellVoiceEngineInfo { + std::string wakeupPhrase; + bool isPcmFromExternal { false }; + int32_t minBufSize { 0 }; + int32_t sampleChannels { 0 }; + int32_t bitsPerSample { 0 }; + int32_t sampleRate { 0 }; +}; + +class IIntellVoiceEngine : public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"HDI.IntellVoice.Engine"); + + enum { + INTELL_VOICE_ENGINE_SET_CALLBACK = 0, + INTELL_VOICE_ENGINE_ATTACH, + INTELL_VOICE_ENGINE_DETACH, + INTELL_VOICE_ENGINE_SET_PARAMETER, + INTELL_VOICE_ENGINE_GET_PARAMETER, + INTELL_VOICE_ENGINE_START, + INTELL_VOICE_ENGINE_STOP, + INTELL_VOICE_ENGINE_WRITE_AUDIO + }; + + virtual void SetCallback(sptr IntellVoiceEngineStub) = 0; + virtual int32_t Attach(const IntellVoiceEngineInfo &info) = 0; + virtual int32_t Detach(void) = 0; + virtual int32_t SetParameter(const std::string &keyValueList) = 0; + virtual std::string GetParameter(const std::string &key) = 0; + virtual int32_t Start(bool isLast) = 0; + virtual int32_t Stop(void) = 0; + virtual int32_t WriteAudio(const uint8_t *buffer, uint32_t size) = 0; +}; +} +} + +#endif diff --git a/services/intell_voice_engine/i_intell_voice_engine_callback.h b/services/intell_voice_engine/i_intell_voice_engine_callback.h new file mode 100755 index 0000000..4def000 --- /dev/null +++ b/services/intell_voice_engine/i_intell_voice_engine_callback.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef I_INTELL_VOICE_ENGINE_CALLBACK_H +#define I_INTELL_VOICE_ENGINE_CALLBACK_H + +#include "iremote_broker.h" +#include "v1_0/intell_voice_engine_types.h" + +namespace OHOS { +namespace IntellVoiceEngine { +using OHOS::HDI::IntelligentVoice::Engine::V1_0::IntellVoiceEngineCallBackEvent; + +class IIntellVoiceEngineEventCallback { +public: + virtual ~IIntellVoiceEngineEventCallback() = default; + virtual void OnEvent(const IntellVoiceEngineCallBackEvent ¶m) = 0; +}; + +class IIntelligentVoiceEngineCallback : public IRemoteBroker { +public: + virtual void OnIntellVoiceEngineEvent(const IntellVoiceEngineCallBackEvent &event) = 0; + enum Code { + ON_INTELL_VOICE_ENGINE_EVENT = 0, + }; + +public: + DECLARE_INTERFACE_DESCRIPTOR(u"IIntelligentVoiceEngineCallback"); +}; +} // namespace IntellVoice +} // namespace OHOS +#endif // I_INTELL_VOICE_ENGINE_CALLBACK_H diff --git a/services/intell_voice_engine/i_intell_voice_service.h b/services/intell_voice_engine/i_intell_voice_service.h new file mode 100755 index 0000000..50142fe --- /dev/null +++ b/services/intell_voice_engine/i_intell_voice_service.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IINTELL_VOICE_SERVICE_H +#define IINTELL_VOICE_SERVICE_H +#include "iremote_broker.h" +#include "i_intell_voice_engine.h" + +namespace OHOS { +namespace IntellVoiceEngine { +class IIntellVoiceService : public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"IntellVoiceFramework.Service"); + + enum { + HDI_INTELL_VOICE_SERVICE_CREATE_ENGINE = 0, + HDI_INTELL_VOICE_SERVICE_RELEASE_ENGINE, + }; + + virtual int32_t CreateIntellVoiceEngine(IntellVoiceEngineType type, sptr &inst) = 0; + virtual int32_t ReleaseIntellVoiceEngine(IntellVoiceEngineType type) = 0; +}; +} +} +#endif diff --git a/services/intell_voice_engine/proxy/engine_callback_inner.cpp b/services/intell_voice_engine/proxy/engine_callback_inner.cpp new file mode 100755 index 0000000..96387ab --- /dev/null +++ b/services/intell_voice_engine/proxy/engine_callback_inner.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "engine_callback_inner.h" +#include "intell_voice_log.h" + +using namespace OHOS::HDI::IntelligentVoice::Engine::V1_0; +#define LOG_TAG "EngineCallbackInner" + +namespace OHOS { +namespace IntellVoiceEngine { +void EngineCallbackInner::OnIntellVoiceEngineEvent(const IntellVoiceEngineCallBackEvent &event) +{ + INTELL_VOICE_LOG_INFO("receive event"); + if (cb_ == nullptr) { + INTELL_VOICE_LOG_INFO("cb is null"); + return; + } + cb_->OnEvent(event); +} + +void EngineCallbackInner::SetEngineEventCallback(std::shared_ptr cb) +{ + cb_ = cb; +} +} +} \ No newline at end of file diff --git a/services/intell_voice_engine/proxy/engine_callback_inner.h b/services/intell_voice_engine/proxy/engine_callback_inner.h new file mode 100755 index 0000000..57a5997 --- /dev/null +++ b/services/intell_voice_engine/proxy/engine_callback_inner.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef ENGINE_CALLBACK_INNER_H +#define ENGINE_CALLBACK_INNER_H + +#include +#include "intell_voice_engine_callback_stub.h" + +namespace OHOS { +namespace IntellVoiceEngine { +class EngineCallbackInner final : public IntellVoiceEngineCallbackStub { +public: + void OnIntellVoiceEngineEvent( + const OHOS::HDI::IntelligentVoice::Engine::V1_0::IntellVoiceEngineCallBackEvent &event) override; + void SetEngineEventCallback(std::shared_ptr cb); +private: + std::shared_ptr cb_; +}; +} +} +#endif \ No newline at end of file diff --git a/services/intell_voice_engine/proxy/intell_voice_engine_callback_stub.cpp b/services/intell_voice_engine/proxy/intell_voice_engine_callback_stub.cpp new file mode 100755 index 0000000..e6b0779 --- /dev/null +++ b/services/intell_voice_engine/proxy/intell_voice_engine_callback_stub.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "intell_voice_engine_callback_stub.h" +#include "intell_voice_log.h" + +#define LOG_TAG "IntellVoiceEngineCallbackStub" + +using namespace OHOS::HDI::IntelligentVoice::Engine::V1_0; + +namespace OHOS { +namespace IntellVoiceEngine { +int IntellVoiceEngineCallbackStub::OnRemoteRequest( + uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + INTELL_VOICE_LOG_INFO("OnRemoteRequest"); + if (data.ReadInterfaceToken() != IIntelligentVoiceEngineCallback::GetDescriptor()) { + INTELL_VOICE_LOG_ERROR("ReadInterfaceToken failed"); + return -1; + } + IIntelligentVoiceEngineCallback::Code msgCode = static_cast(code); + switch (msgCode) { + case ON_INTELL_VOICE_ENGINE_EVENT: { + OnIntellVoiceEngineEventInner(data); + reply.WriteInt32(0); + break; + } + default: { + INTELL_VOICE_LOG_WARN("invalid msgCode:%{public}d", msgCode); + reply.WriteInt32(-1); + break; + } + } + return 0; +} + +void IntellVoiceEngineCallbackStub::OnIntellVoiceEngineEventInner(MessageParcel &data) +{ + IntellVoiceEngineCallBackEvent event = { + .msgId = static_cast(data.ReadInt32()), + .result = static_cast(data.ReadInt32()), + .info = data.ReadString(), + }; + OnIntellVoiceEngineEvent(event); +} +} +} \ No newline at end of file diff --git a/services/intell_voice_engine/proxy/intell_voice_engine_callback_stub.h b/services/intell_voice_engine/proxy/intell_voice_engine_callback_stub.h new file mode 100755 index 0000000..46a304b --- /dev/null +++ b/services/intell_voice_engine/proxy/intell_voice_engine_callback_stub.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef INTELL_VOICE_ENGINE_CALLBACK_STUB_H +#define INTELL_VOICE_ENGINE_CALLBACK_STUB_H + +#include "iremote_stub.h" +#include "i_intell_voice_engine_callback.h" + +namespace OHOS { +namespace IntellVoiceEngine { +class IntellVoiceEngineCallbackStub : public IRemoteStub { +public: + int OnRemoteRequest(uint32_t code, MessageParcel &data, + MessageParcel &reply, MessageOption &option) override; +private: + void OnIntellVoiceEngineEventInner(MessageParcel &data); +}; +} +} +#endif \ No newline at end of file diff --git a/services/intell_voice_engine/proxy/intell_voice_engine_proxy.cpp b/services/intell_voice_engine/proxy/intell_voice_engine_proxy.cpp new file mode 100755 index 0000000..4b6bbe7 --- /dev/null +++ b/services/intell_voice_engine/proxy/intell_voice_engine_proxy.cpp @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "intell_voice_engine_proxy.h" +#include "intell_voice_log.h" + +#define LOG_TAG "IntellVoiceEngineProxy" + +namespace OHOS { +namespace IntellVoiceEngine { +void IntellVoiceEngineProxy::SetCallback(sptr object) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (object == nullptr) { + INTELL_VOICE_LOG_ERROR("object is null"); + return; + } + + data.WriteInterfaceToken(IIntellVoiceEngine::GetDescriptor()); + data.WriteRemoteObject(object); + Remote()->SendRequest(INTELL_VOICE_ENGINE_SET_CALLBACK, data, reply, option); +} + +int32_t IntellVoiceEngineProxy::Attach(const IntellVoiceEngineInfo &info) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + data.WriteInterfaceToken(IIntellVoiceEngine::GetDescriptor()); + data.WriteString(info.wakeupPhrase); + data.WriteBool(info.isPcmFromExternal); + data.WriteInt32(info.minBufSize); + data.WriteInt32(info.sampleChannels); + data.WriteInt32(info.bitsPerSample); + data.WriteInt32(info.sampleRate); + + Remote()->SendRequest(INTELL_VOICE_ENGINE_ATTACH, data, reply, option); + + INTELL_VOICE_LOG_INFO("Attach call"); + return reply.ReadInt32(); +} + +int32_t IntellVoiceEngineProxy::Detach(void) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + data.WriteInterfaceToken(IIntellVoiceEngine::GetDescriptor()); + Remote()->SendRequest(INTELL_VOICE_ENGINE_DETACH, data, reply, option); + return reply.ReadInt32(); +} + +int32_t IntellVoiceEngineProxy::SetParameter(const std::string &keyValueList) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + data.WriteInterfaceToken(IIntellVoiceEngine::GetDescriptor()); + data.WriteString(keyValueList); + Remote()->SendRequest(INTELL_VOICE_ENGINE_SET_PARAMETER, data, reply, option); + return reply.ReadInt32(); +} + +std::string IntellVoiceEngineProxy::GetParameter(const std::string &key) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + data.WriteInterfaceToken(IIntellVoiceEngine::GetDescriptor()); + data.WriteString(key); + + Remote()->SendRequest(INTELL_VOICE_ENGINE_GET_PARAMETER, data, reply, option); + return reply.ReadString(); +} + +int32_t IntellVoiceEngineProxy::Start(bool isLast) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + data.WriteInterfaceToken(IIntellVoiceEngine::GetDescriptor()); + + Remote()->SendRequest(INTELL_VOICE_ENGINE_START, data, reply, option); + return reply.ReadInt32(); +} + +int32_t IntellVoiceEngineProxy::Stop(void) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + data.WriteInterfaceToken(IIntellVoiceEngine::GetDescriptor()); + + Remote()->SendRequest(INTELL_VOICE_ENGINE_STOP, data, reply, option); + return reply.ReadInt32(); +} + +int32_t IntellVoiceEngineProxy::WriteAudio(const uint8_t *buffer, uint32_t size) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + data.WriteInterfaceToken(IIntellVoiceEngine::GetDescriptor()); + data.WriteUint32(size); + data.WriteBuffer(buffer, size); + + Remote()->SendRequest(INTELL_VOICE_ENGINE_WRITE_AUDIO, data, reply, option); + return reply.ReadInt32(); +} +} +} diff --git a/services/intell_voice_engine/proxy/intell_voice_engine_proxy.h b/services/intell_voice_engine/proxy/intell_voice_engine_proxy.h new file mode 100755 index 0000000..2c2a65c --- /dev/null +++ b/services/intell_voice_engine/proxy/intell_voice_engine_proxy.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTELL_VOICE_ENGINE_PROXY_H +#define INTELL_VOICE_ENGINE_PROXY_H + +#include +#include "i_intell_voice_engine.h" + +namespace OHOS { +namespace IntellVoiceEngine { +class IntellVoiceEngineProxy : public IRemoteProxy { +public: + explicit IntellVoiceEngineProxy(const sptr &impl) : IRemoteProxy(impl) {}; + virtual ~IntellVoiceEngineProxy() {}; + void SetCallback(sptr object) override; + int32_t Attach(const IntellVoiceEngineInfo &info) override; + int32_t Detach(void) override; + int32_t SetParameter(const std::string &keyValueList) override; + std::string GetParameter(const std::string &key) override; + int32_t Start(bool isLast) override; + int32_t Stop(void) override; + int32_t WriteAudio(const uint8_t *buffer, uint32_t size) override; + +private: + static inline BrokerDelegator delegator_; +}; +} +} + +#endif diff --git a/services/intell_voice_engine/proxy/intell_voice_service_proxy.cpp b/services/intell_voice_engine/proxy/intell_voice_service_proxy.cpp new file mode 100755 index 0000000..cb1c555 --- /dev/null +++ b/services/intell_voice_engine/proxy/intell_voice_service_proxy.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "intell_voice_service_proxy.h" +#include "intell_voice_log.h" + +#define LOG_TAG "IntellVoiceServiceProxy" +namespace OHOS { +namespace IntellVoiceEngine { +int32_t IntellVoiceServiceProxy::CreateIntellVoiceEngine(IntellVoiceEngineType type, sptr &inst) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + data.WriteInterfaceToken(IIntellVoiceService::GetDescriptor()); + data.WriteInt32(static_cast(type)); + + Remote()->SendRequest(HDI_INTELL_VOICE_SERVICE_CREATE_ENGINE, data, reply, option); + + sptr remote = reply.ReadRemoteObject(); + if (remote == nullptr) { + INTELL_VOICE_LOG_ERROR("Create engine failed, engine is null"); + return -1; + } + inst = iface_cast(remote); + + return 0; +} + +int32_t IntellVoiceServiceProxy::ReleaseIntellVoiceEngine(IntellVoiceEngineType type) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + data.WriteInterfaceToken(IIntellVoiceService::GetDescriptor()); + data.WriteInt32(type); + + Remote()->SendRequest(HDI_INTELL_VOICE_SERVICE_RELEASE_ENGINE, data, reply, option); + return reply.ReadInt32(); +} +} +} diff --git a/services/intell_voice_engine/proxy/intell_voice_service_proxy.h b/services/intell_voice_engine/proxy/intell_voice_service_proxy.h new file mode 100755 index 0000000..5b8524e --- /dev/null +++ b/services/intell_voice_engine/proxy/intell_voice_service_proxy.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTELL_VOICE_SERVICE_PROXY_H +#define INTELL_VOICE_SERVICE_PROXY_H + +#include +#include "i_intell_voice_service.h" +#include "i_intell_voice_engine.h" + +namespace OHOS { +namespace IntellVoiceEngine { +class IntellVoiceServiceProxy : public IRemoteProxy { +public: + explicit IntellVoiceServiceProxy(const sptr &impl) : IRemoteProxy(impl) {} + virtual ~IntellVoiceServiceProxy() {}; + + int32_t CreateIntellVoiceEngine(IntellVoiceEngineType type, sptr &inst) override; + int32_t ReleaseIntellVoiceEngine(IntellVoiceEngineType type) override; + +private: + static inline BrokerDelegator delegator_; +}; +} +} + +#endif diff --git a/services/intell_voice_engine/server/base/adapter_callback_service.cpp b/services/intell_voice_engine/server/base/adapter_callback_service.cpp new file mode 100755 index 0000000..032c29f --- /dev/null +++ b/services/intell_voice_engine/server/base/adapter_callback_service.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "adapter_callback_service.h" +#include "intell_voice_log.h" + +#define LOG_TAG "AdapterCallbackService" + +namespace OHOS { +namespace IntellVoiceEngine { +int32_t AdapterCallbackService::OnIntellVoiceHdiEvent(const IntellVoiceEngineCallBackEvent& event) +{ + if (listener_ == nullptr) { + INTELL_VOICE_LOG_ERROR("listener_ is nullptr"); + return -1; + } + INTELL_VOICE_LOG_INFO("send hdi event"); + listener_->OnIntellVoiceHdiEvent(event); + return 0; +} +} +} \ No newline at end of file diff --git a/services/intell_voice_engine/server/base/adapter_callback_service.h b/services/intell_voice_engine/server/base/adapter_callback_service.h new file mode 100755 index 0000000..e7c14e1 --- /dev/null +++ b/services/intell_voice_engine/server/base/adapter_callback_service.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef ADAPTER_CALLBACK_SERVICE_H +#define ADAPTER_CALLBACK_SERVICE_H + +#include "v1_0/iintell_voice_engine_callback.h" +#include "intell_voice_adapter_listener.h" + +namespace OHOS { +namespace IntellVoiceEngine { +using OHOS::HDI::IntelligentVoice::Engine::V1_0::IIntellVoiceEngineCallback; +using OHOS::HDI::IntelligentVoice::Engine::V1_0::IntellVoiceEngineCallBackEvent; + +class AdapterCallbackService final: public IIntellVoiceEngineCallback { +public: + AdapterCallbackService(std::shared_ptr listener) : listener_(listener) {} + virtual ~AdapterCallbackService() = default; + + int32_t OnIntellVoiceHdiEvent(const IntellVoiceEngineCallBackEvent& event) override; +private: + std::shared_ptr listener_ = nullptr; +}; +} +} +#endif \ No newline at end of file diff --git a/services/intell_voice_engine/server/base/audio_source.cpp b/services/intell_voice_engine/server/base/audio_source.cpp new file mode 100755 index 0000000..e1f15ab --- /dev/null +++ b/services/intell_voice_engine/server/base/audio_source.cpp @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "audio_source.h" + +#include "securec.h" +#include "time_util.h" +#include "intell_voice_log.h" +#include "memory_guard.h" + +using namespace OHOS::AudioStandard; +using namespace OHOS::IntellVoiceUtils; +#define LOG_TAG "AudioSource" + +namespace OHOS { +namespace IntellVoiceEngine { +static const std::string PCM_DIR = "/data/data/intell_voice/pcm_data/"; + +AudioSource::AudioSource(uint32_t minBufferSize, uint32_t bufferCnt, + std::unique_ptr listener, const OHOS::AudioStandard::AudioCapturerOptions &capturerOptions) + : minBufferSize_(minBufferSize), bufferCnt_(bufferCnt), listener_(std::move(listener)) +{ + capturerOptions_.streamInfo.samplingRate = capturerOptions.streamInfo.samplingRate; + capturerOptions_.streamInfo.encoding = capturerOptions.streamInfo.encoding; + capturerOptions_.streamInfo.format = capturerOptions.streamInfo.format; + capturerOptions_.streamInfo.channels = capturerOptions.streamInfo.channels; + capturerOptions_.capturerInfo.sourceType = capturerOptions.capturerInfo.sourceType; + capturerOptions_.capturerInfo.capturerFlags = capturerOptions.capturerInfo.capturerFlags; + + audioCapturer_ = AudioCapturer::Create(capturerOptions_); + if (audioCapturer_ == nullptr) { + INTELL_VOICE_LOG_ERROR("create audio capturer failed"); + } +} + +AudioSource::~AudioSource() +{ + audioCapturer_ = nullptr; +} + +bool AudioSource::Start() +{ + INTELL_VOICE_LOG_INFO("enter"); + if (audioCapturer_ == nullptr) { + INTELL_VOICE_LOG_ERROR("audioCapturer_ is nullptr"); + return false; + } + + if (listener_ == nullptr) { + INTELL_VOICE_LOG_ERROR("listener_ is nullptr"); + return false; + } + + if (minBufferSize_ == 0) { + INTELL_VOICE_LOG_ERROR("minBufferSize_ is invalid"); + return false; + } + + buffer_ = std::shared_ptr(new uint8_t[minBufferSize_], [](uint8_t *p) { delete[] p; }); + if (buffer_ == nullptr) { + INTELL_VOICE_LOG_ERROR("malloc buffer failed"); + return false; + } + + auto path = PCM_DIR + TimeUtil::GetCurrTime() + ".pcm"; + fileStream_ = std::make_unique(path); + if (fileStream_ == nullptr) { + INTELL_VOICE_LOG_ERROR("open debug record file failed"); + return false; + } + + if (!audioCapturer_->Start()) { + INTELL_VOICE_LOG_ERROR("start audio capturer failed"); + fileStream_->close(); + fileStream_ = nullptr; + return false; + } + + isReading_.store(true); + std::thread t1(std::bind(&AudioSource::ReadThread, this)); + readThread_ = std::move(t1); + return true; +} + +void AudioSource::ReadThread() +{ + uint32_t readCnt = 0; + bool isError = true; + while (isReading_.load()) { + if (readCnt >= bufferCnt_) { + INTELL_VOICE_LOG_INFO("finish reading data"); + isError = false; + break; + } + + if (!Read()) { + INTELL_VOICE_LOG_WARN("failed to read data"); + break; + } + ++readCnt; + } + + if (listener_ != nullptr) { + listener_->bufferEndCb_(isError); + } +} + +bool AudioSource::Read() +{ + size_t bytesRead = 0; + while (bytesRead < minBufferSize_) { + int32_t len = audioCapturer_->Read(*(buffer_.get() + bytesRead), minBufferSize_ - bytesRead, 0); + if (len >= 0) { + bytesRead += static_cast(len); + } else { + INTELL_VOICE_LOG_ERROR("read data error, len is %{public}d", len); + break; + } + } + + if (bytesRead != minBufferSize_) { + INTELL_VOICE_LOG_ERROR("failed to read data, bytesRead is %zu", bytesRead); + return false; + } + + if (fileStream_ != nullptr) { + fileStream_->write(reinterpret_cast(buffer_.get()), minBufferSize_); + } + + if (listener_ != nullptr) { + listener_->readBufferCb_(buffer_.get(), minBufferSize_); + } + return true; +} + +void AudioSource::Stop() +{ + INTELL_VOICE_LOG_INFO("enter"); + if (!isReading_.load()) { + INTELL_VOICE_LOG_INFO("already stop"); + return; + } + + MemoryGuard memoryGuard; + + isReading_.store(false); + readThread_.join(); + + if (fileStream_ != nullptr) { + fileStream_->close(); + fileStream_ = nullptr; + } + + if (audioCapturer_ == nullptr) { + INTELL_VOICE_LOG_ERROR("audioCapturer_ is nullptr"); + return; + } + + if (!audioCapturer_->Stop()) { + INTELL_VOICE_LOG_ERROR("stop audio capturer error"); + } + + if (!audioCapturer_->Release()) { + INTELL_VOICE_LOG_ERROR("release audio capturer error"); + } + + audioCapturer_ = nullptr; + listener_ = nullptr; +} +} +} \ No newline at end of file diff --git a/services/intell_voice_engine/server/base/audio_source.h b/services/intell_voice_engine/server/base/audio_source.h new file mode 100755 index 0000000..5a46b30 --- /dev/null +++ b/services/intell_voice_engine/server/base/audio_source.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef AUDIO_SOURCE_H +#define AUDIO_SOURCE_H + +#include +#include +#include +#include +#include +#include "audio_capturer.h" +#include "audio_info.h" + +namespace OHOS { +namespace IntellVoiceEngine { +using OnReadBufferCb = std::function; +using OnBufferEndCb = std::function; + +struct AudioSourceListener { + AudioSourceListener(OnReadBufferCb readBufferCb, OnBufferEndCb bufferEndCb) + : readBufferCb_(readBufferCb), bufferEndCb_(bufferEndCb) {} + OnReadBufferCb readBufferCb_; + OnBufferEndCb bufferEndCb_; +}; + +class AudioSource { +public: + AudioSource(uint32_t minBufferSize, uint32_t bufferCnt, std::unique_ptr listener, + const OHOS::AudioStandard::AudioCapturerOptions &capturerOptions); + ~AudioSource(); + bool Start(); + void Stop(); + +private: + void ReadThread(); + bool Read(); + +private: + uint32_t minBufferSize_ = 0; + uint32_t bufferCnt_ = 0; + std::unique_ptr listener_ = nullptr; + std::atomic isReading_ = false; + std::thread readThread_; + OHOS::AudioStandard::AudioCapturerOptions capturerOptions_; + std::shared_ptr buffer_ = nullptr; + std::unique_ptr fileStream_ = nullptr; + std::unique_ptr audioCapturer_ = nullptr; +}; +} +} +#endif \ No newline at end of file diff --git a/services/intell_voice_engine/server/base/engine_base.cpp b/services/intell_voice_engine/server/base/engine_base.cpp new file mode 100755 index 0000000..a4a1293 --- /dev/null +++ b/services/intell_voice_engine/server/base/engine_base.cpp @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "engine_base.h" + +#include "intell_voice_log.h" +#include "string_util.h" + +using namespace OHOS::IntellVoiceUtils; +using namespace OHOS::HDI::IntelligentVoice::Engine::V1_0; +#define LOG_TAG "EngineBase" + +namespace OHOS { +namespace IntellVoiceEngine { +EngineBase::EngineBase() +{ + INTELL_VOICE_LOG_INFO("constructor"); + desc_.adapterType = ADAPTER_TYPE_BUT; +} + +int32_t EngineBase::SetParameter(const std::string &keyValueList) +{ + std::lock_guard lock(mutex_); + if (adapter_ == nullptr) { + INTELL_VOICE_LOG_ERROR("adapter is nullptr"); + return -1; + } + return adapter_->SetParameter(keyValueList); +} + +std::string EngineBase::GetParameter(const std::string &key) +{ + std::lock_guard lock(mutex_); + if (adapter_ == nullptr) { + INTELL_VOICE_LOG_ERROR("adapter is nullptr"); + return ""; + } + + std::string value; + adapter_->GetParameter(key, value); + return value; +} + +int32_t EngineBase::WriteAudio(const uint8_t *buffer, uint32_t size) +{ + std::lock_guard lock(mutex_); + if (adapter_ == nullptr) { + INTELL_VOICE_LOG_ERROR("adapter is nullptr"); + return -1; + } + std::vector audioBuff(&buffer[0], &buffer[size]); + return adapter_->WriteAudio(audioBuff); +} + +int32_t EngineBase::Stop() +{ + std::lock_guard lock(mutex_); + if (adapter_ == nullptr) { + INTELL_VOICE_LOG_ERROR("adapter is nullptr"); + return -1; + } + return adapter_->Stop(); +} + +void EngineBase::SplitStringToKVPair(const std::string &inputStr, std::map &kvpairs) +{ + std::vector paramsList; + StringUtil::Split(inputStr, ";", paramsList); + for (auto &it : paramsList) { + std::string key; + std::string value; + if (StringUtil::SplitLineToPair(it, key, value)) { + kvpairs[key] = value; + INTELL_VOICE_LOG_INFO("key:%{public}s, value:%{public}s", key.c_str(), value.c_str()); + } + } +} +} +} \ No newline at end of file diff --git a/services/intell_voice_engine/server/base/engine_base.h b/services/intell_voice_engine/server/base/engine_base.h new file mode 100755 index 0000000..14041a0 --- /dev/null +++ b/services/intell_voice_engine/server/base/engine_base.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef ENGINE_BASE_H +#define ENGINE_BASE_H +#include +#include +#include +#include +#include "intell_voice_engine_stub.h" +#include "v1_0/iintell_voice_engine_adapter.h" + +namespace OHOS { +namespace IntellVoiceEngine { +enum EngineRelationType { + CONCURRENCY_TYPE, + PREEMPTION_TYPE, + REPLACEMENT_TYPE, +}; + +class EngineBase : public IntellVoiceEngineStub { +public: + ~EngineBase() = default; + virtual bool Init() = 0; + int32_t SetParameter(const std::string &keyValueList) override; + std::string GetParameter(const std::string &key) override; + int32_t WriteAudio(const uint8_t *buffer, uint32_t size) override; + int32_t Stop() override; + virtual void OnDetected() {}; + bool IsRunning() + { + return isRunning_; + } + EngineRelationType GetEngineRelationType() + { + return type_; + } + int32_t GetPriority() + { + return priority_; + } + +protected: + EngineBase(); + void SplitStringToKVPair(const std::string &inputStr, std::map &kvpairs); + std::mutex mutex_; + sptr adapter_ = nullptr; + OHOS::HDI::IntelligentVoice::Engine::V1_0::IntellVoiceEngineAdapterDescriptor desc_; + + bool isRunning_ = false; + EngineRelationType type_ = CONCURRENCY_TYPE; + int32_t priority_ = 0; +}; +} +} +#endif \ No newline at end of file diff --git a/services/intell_voice_engine/server/base/engine_factory.cpp b/services/intell_voice_engine/server/base/engine_factory.cpp new file mode 100755 index 0000000..20168bc --- /dev/null +++ b/services/intell_voice_engine/server/base/engine_factory.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "engine_factory.h" +#include "enroll_engine.h" +#include "wakeup_engine.h" +#include "intell_voice_log.h" +#include "intell_voice_generic_factory.h" + +using namespace OHOS::IntellVoiceUtils; +#define LOG_TAG "EngineFactory" + +namespace OHOS { +namespace IntellVoiceEngine { +sptr EngineFactory::CreateEngineInst(IntellVoiceEngineType type) +{ + sptr engine = nullptr; + switch (type) { + case INTELL_VOICE_ENROLL: + engine = SptrFactory::CreateInstance(); + break; + case INTELL_VOICE_WAKEUP: + engine = SptrFactory::CreateInstance(); + break; + case INTELL_VOICE_UPDATE: + default: + INTELL_VOICE_LOG_INFO("create engine enter, type:%d", type); + break; + } + + return engine; +} +} +} diff --git a/services/intell_voice_engine/server/base/engine_factory.h b/services/intell_voice_engine/server/base/engine_factory.h new file mode 100755 index 0000000..9e31f44 --- /dev/null +++ b/services/intell_voice_engine/server/base/engine_factory.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef ENGINE_FACTORY_H +#define ENGINE_FACTORY_H + +#include "engine_base.h" + +namespace OHOS { +namespace IntellVoiceEngine { +class EngineFactory { +public: + EngineFactory() = default; + ~EngineFactory() = default; + static sptr CreateEngineInst(IntellVoiceEngineType type); +}; +} +} +#endif \ No newline at end of file diff --git a/services/intell_voice_engine/server/base/file_source.cpp b/services/intell_voice_engine/server/base/file_source.cpp new file mode 100755 index 0000000..a3be822 --- /dev/null +++ b/services/intell_voice_engine/server/base/file_source.cpp @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "file_source.h" + +#include "securec.h" +#include "intell_voice_log.h" +#include "memory_guard.h" + +using namespace OHOS::IntellVoiceUtils; +#define LOG_TAG "FileSource" + +namespace OHOS { +namespace IntellVoiceEngine { +FileSource::FileSource(uint32_t minBufferSize, uint32_t bufferCnt, const std::string &filePath, + std::unique_ptr listener) + : minBufferSize_(minBufferSize), bufferCnt_(bufferCnt), filePath_(filePath), listener_(std::move(listener)) +{ +} + +FileSource::~FileSource() +{ + if (isReading_.load()) { + isReading_.store(false); + readThread_.join(); + } +} + +bool FileSource::Start() +{ + INTELL_VOICE_LOG_INFO("enter"); + if (listener_ == nullptr) { + INTELL_VOICE_LOG_ERROR("listener_ is nullptr"); + return false; + } + + if (minBufferSize_ == 0) { + INTELL_VOICE_LOG_ERROR("minBufferSize_ is invalid"); + return false; + } + + buffer_ = std::shared_ptr(new uint8_t[minBufferSize_], [](uint8_t *p) { delete[] p; }); + if (buffer_ == nullptr) { + INTELL_VOICE_LOG_ERROR("malloc buffer failed"); + return false; + } + + fileIn_ = std::make_unique(filePath_, std::ios::binary); + if (fileIn_ == nullptr) { + INTELL_VOICE_LOG_ERROR("open input file failed"); + return false; + } + + fileIn_->seekg(0, fileIn_->end); + uint32_t size = static_cast(fileIn_->tellg()); + if (size < minBufferSize_ * bufferCnt_) { + INTELL_VOICE_LOG_ERROR("file size:%{public}u is smaller than required", size); + fileIn_->close(); + fileIn_ = nullptr; + return false; + } + + isReading_.store(true); + std::thread t1(std::bind(&FileSource::ReadThread, this)); + readThread_ = std::move(t1); + return true; +} + +void FileSource::ReadThread() +{ + uint32_t readCnt = 0; + bool isError = true; + if (fileIn_ == nullptr) { + INTELL_VOICE_LOG_ERROR("fileIn_ is nullptr"); + return; + } + + fileIn_->seekg(0, fileIn_->beg); + + while (isReading_.load()) { + if (readCnt >= bufferCnt_) { + INTELL_VOICE_LOG_INFO("finish reading data"); + isError = false; + break; + } + + if (!(fileIn_->read(reinterpret_cast(buffer_.get()), minBufferSize_))) { + INTELL_VOICE_LOG_ERROR("failed to read file"); + break; + } + + if (listener_ != nullptr) { + listener_->fileBufferCb_(buffer_.get(), minBufferSize_); + } + + ++readCnt; + } + + if (listener_ != nullptr) { + listener_->fileEndCb_(isError); + } +} + +void FileSource::Stop() +{ + INTELL_VOICE_LOG_INFO("enter"); + MemoryGuard memoryGuard; + if (isReading_.load()) { + isReading_.store(false); + readThread_.join(); + } + + if (fileIn_ != nullptr) { + fileIn_->close(); + fileIn_ = nullptr; + } + + buffer_ = nullptr; + listener_ = nullptr; +} +} +} \ No newline at end of file diff --git a/services/intell_voice_engine/server/base/file_source.h b/services/intell_voice_engine/server/base/file_source.h new file mode 100755 index 0000000..bbf1ed1 --- /dev/null +++ b/services/intell_voice_engine/server/base/file_source.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef FILE_SOURCE_H +#define FILE_SOURCE_H + +#include +#include +#include +#include +#include +#include + +namespace OHOS { +namespace IntellVoiceEngine { +using OnFileBufferCb = std::function; +using OnFileEndCb = std::function; + +struct FileSourceListener { + FileSourceListener(OnFileBufferCb fileBufferCb, OnFileEndCb fileEndCb) + : fileBufferCb_(fileBufferCb), fileEndCb_(fileEndCb) {} + OnFileBufferCb fileBufferCb_; + OnFileEndCb fileEndCb_; +}; + +class FileSource { +public: + FileSource(uint32_t minBufferSize, uint32_t bufferCnt, const std::string &filePath, + std::unique_ptr listener); + ~FileSource(); + bool Start(); + void Stop(); + +private: + void ReadThread(); + bool Read(); + +private: + uint32_t minBufferSize_ = 0; + uint32_t bufferCnt_ = 0; + std::string filePath_; + std::unique_ptr listener_ = nullptr; + std::atomic isReading_ = false; + std::thread readThread_; + std::unique_ptr fileIn_ = nullptr; + std::shared_ptr buffer_ = nullptr; +}; +} +} +#endif \ No newline at end of file diff --git a/services/intell_voice_engine/server/base/intell_voice_adapter_listener.h b/services/intell_voice_engine/server/base/intell_voice_adapter_listener.h new file mode 100755 index 0000000..c47640f --- /dev/null +++ b/services/intell_voice_engine/server/base/intell_voice_adapter_listener.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef INTELL_VOICE_ADAPTER_LISTENER_H +#define INTELL_VOICE_ADAPTER_LISTENER_H + +#include "v1_0/intell_voice_engine_types.h" + +namespace OHOS { +namespace IntellVoiceEngine { +class IntellVoiceAdapterListener { +public: + virtual ~IntellVoiceAdapterListener() = default; + virtual void OnIntellVoiceHdiEvent( + const OHOS::HDI::IntelligentVoice::Engine::V1_0::IntellVoiceEngineCallBackEvent &event) = 0; +}; +} // namespace IntellVoice +} // namespace OHOS +#endif \ No newline at end of file diff --git a/services/intell_voice_engine/server/enroll/enroll_adapter_listener.cpp b/services/intell_voice_engine/server/enroll/enroll_adapter_listener.cpp new file mode 100755 index 0000000..0da3456 --- /dev/null +++ b/services/intell_voice_engine/server/enroll/enroll_adapter_listener.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "enroll_adapter_listener.h" + +#include +#include "intell_voice_log.h" + +#define LOG_TAG "EnrollAdapterListener" + +using namespace OHOS::HDI::IntelligentVoice::Engine::V1_0; + +namespace OHOS { +namespace IntellVoiceEngine { +EnrollAdapterListener::EnrollAdapterListener(const sptr &cb, + OnEnrollEventCb enrollEventCb) : cb_(cb), enrollEventCb_(enrollEventCb) +{ + INTELL_VOICE_LOG_INFO("constructor"); +} + +EnrollAdapterListener::~EnrollAdapterListener() +{ + INTELL_VOICE_LOG_INFO("destructor"); +} + +void EnrollAdapterListener::OnIntellVoiceHdiEvent(const IntellVoiceEngineCallBackEvent& event) +{ + INTELL_VOICE_LOG_INFO("OnIntellVoiceHdiEvent"); + + enrollEventCb_(event.msgId, event.result); + + if (cb_ != nullptr) { + cb_->OnIntellVoiceEngineEvent(event); + } +} +} +} \ No newline at end of file diff --git a/services/intell_voice_engine/server/enroll/enroll_adapter_listener.h b/services/intell_voice_engine/server/enroll/enroll_adapter_listener.h new file mode 100755 index 0000000..5ba7940 --- /dev/null +++ b/services/intell_voice_engine/server/enroll/enroll_adapter_listener.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef ENROLL_ADAPTER_LISTENER_H +#define ENROLL_ADAPTER_LISTENER_H + +#include +#include "intell_voice_adapter_listener.h" +#include "i_intell_voice_engine_callback.h" + +namespace OHOS { +namespace IntellVoiceEngine { +using OnEnrollEventCb = std::function; + +class EnrollAdapterListener : public IntellVoiceAdapterListener { +public: + EnrollAdapterListener(const sptr &cb, OnEnrollEventCb enrollEventCb); + ~EnrollAdapterListener(); + + void OnIntellVoiceHdiEvent( + const OHOS::HDI::IntelligentVoice::Engine::V1_0::IntellVoiceEngineCallBackEvent& event) override; + +private: + sptr cb_ = nullptr; + OnEnrollEventCb enrollEventCb_; +}; +} +} +#endif \ No newline at end of file diff --git a/services/intell_voice_engine/server/enroll/enroll_engine.cpp b/services/intell_voice_engine/server/enroll/enroll_engine.cpp new file mode 100755 index 0000000..0483a18 --- /dev/null +++ b/services/intell_voice_engine/server/enroll/enroll_engine.cpp @@ -0,0 +1,377 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "enroll_engine.h" +#include +#include "securec.h" +#include "intell_voice_log.h" + +#include "v1_0/iintell_voice_engine_manager.h" +#include "v1_0/iintell_voice_engine_callback.h" + +#include "enroll_adapter_listener.h" +#include "time_util.h" +#include "scope_guard.h" +#include "trigger_manager.h" +#include "adapter_callback_service.h" +#include "intell_voice_service_manager.h" + +#define LOG_TAG "EnrollEngine" + +using namespace OHOS::IntellVoiceTrigger; +using namespace OHOS::HDI::IntelligentVoice::Engine::V1_0; +using namespace OHOS::IntellVoiceUtils; +using namespace OHOS::AudioStandard; + +namespace OHOS { +namespace IntellVoiceEngine { +static constexpr uint32_t MIN_BUFFER_SIZE = 1280; // 16 * 2 * 40ms +static constexpr uint32_t INTERVAL = 125; // 125 * 40ms = 5s +EnrollEngine::EnrollEngine() +{ + INTELL_VOICE_LOG_INFO("enter"); + + capturerOptions_.streamInfo.samplingRate = AudioSamplingRate::SAMPLE_RATE_16000; + capturerOptions_.streamInfo.encoding = AudioEncodingType::ENCODING_PCM; + capturerOptions_.streamInfo.format = AudioSampleFormat::SAMPLE_S16LE; + capturerOptions_.streamInfo.channels = AudioChannel::MONO; + capturerOptions_.capturerInfo.sourceType = SourceType::SOURCE_TYPE_MIC; + capturerOptions_.capturerInfo.capturerFlags = 0; +} + +EnrollEngine::~EnrollEngine() +{ + auto mgr = IIntellVoiceEngineManager::Get(); + if (mgr != nullptr) { + mgr->ReleaseAdapter(desc_); + } + adapter_ = nullptr; + callback_ = nullptr; + if (audioSource_ != nullptr) { + audioSource_->Stop(); + audioSource_ = nullptr; + } +} + +void EnrollEngine::OnEnrollEvent(int32_t msgId, int32_t result) +{ + if (msgId == INTELL_VOICE_ENGINE_MSG_ENROLL_COMPLETE) { + std::thread(&EnrollEngine::OnEnrollComplete, this).detach(); + } else if (msgId == INTELL_VOICE_ENGINE_MSG_COMMIT_ENROLL_COMPLETE) { + std::lock_guard lock(mutex_); + enrollResult_ = result; + } else { + } +} + +void EnrollEngine::OnEnrollComplete() +{ + StopAudioSource(); +} + +bool EnrollEngine::Init() +{ + desc_.adapterType = ENROLL_ADAPTER_TYPE; + auto mgr = IIntellVoiceEngineManager::Get(); + if (mgr == nullptr) { + INTELL_VOICE_LOG_ERROR("failed to get engine manager"); + return false; + } + + mgr->CreateAdapter(desc_, adapter_); + if (adapter_ == nullptr) { + INTELL_VOICE_LOG_ERROR("adapter is nullptr"); + return false; + } + + return true; +} + +void EnrollEngine::SetCallback(sptr object) +{ + std::lock_guard lock(mutex_); + if (adapter_ == nullptr) { + INTELL_VOICE_LOG_ERROR("adapter is nullptr"); + return; + } + + sptr callback = iface_cast(object); + if (callback == nullptr) { + INTELL_VOICE_LOG_ERROR("callback is nullptr"); + return; + } + + std::shared_ptr listener = std::make_shared(callback, + std::bind(&EnrollEngine::OnEnrollEvent, this, std::placeholders::_1, std::placeholders::_2)); + if (listener == nullptr) { + INTELL_VOICE_LOG_ERROR("listener is nullptr"); + return; + } + + callback_ = sptr(new (std::nothrow) AdapterCallbackService(listener)); + if (callback_ == nullptr) { + INTELL_VOICE_LOG_ERROR("callback_ is nullptr"); + return; + } + + adapter_->SetCallback(callback_); +} + +int32_t EnrollEngine::Attach(const IntellVoiceEngineInfo &info) +{ + std::lock_guard lock(mutex_); + INTELL_VOICE_LOG_INFO("attach"); + if (adapter_ == nullptr) { + INTELL_VOICE_LOG_ERROR("adapter is nullptr"); + return -1; + } + + isPcmFromExternal_ = info.isPcmFromExternal; + + IntellVoiceEngineAdapterInfo adapterInfo = { + .wakeupPhrase = info.wakeupPhrase, + .minBufSize = info.minBufSize, + .sampleChannels = info.sampleChannels, + .bitsPerSample = info.bitsPerSample, + .sampleRate = info.sampleRate, + }; + return adapter_->Attach(adapterInfo); +} + +int32_t EnrollEngine::Detach(void) +{ + std::lock_guard lock(mutex_); + if (adapter_ == nullptr) { + INTELL_VOICE_LOG_ERROR("adapter is nullptr"); + return -1; + } + + if (enrollResult_ == 0) { + ProcDspModel(); + } + return adapter_->Detach(); +} + +int32_t EnrollEngine::Start(bool isLast) +{ + std::lock_guard lock(mutex_); + INTELL_VOICE_LOG_INFO("enter"); + if (audioSource_ != nullptr) { + INTELL_VOICE_LOG_ERROR("audioSource_ existed, wait for last start to finish"); + return -1; + } + + if (adapter_ == nullptr) { + INTELL_VOICE_LOG_ERROR("adapter is nullptr"); + return -1; + } + + if (IntellVoiceServiceManager::GetInstance()->ApplyArbitration(INTELL_VOICE_ENROLL, ENGINE_EVENT_START) != + ARBITRATION_OK) { + INTELL_VOICE_LOG_ERROR("policy manager reject to start engine"); + return 0; + } + + StartInfo info = { + .isLast = isLast, + }; + if (adapter_->Start(info)) { + INTELL_VOICE_LOG_ERROR("start adapter failed"); + return -1; + } + + if (isPcmFromExternal_) { + INTELL_VOICE_LOG_INFO("pcm is from external"); + return 0; + } + + if (!StartAudioSource()) { + INTELL_VOICE_LOG_ERROR("start audio source failed"); + adapter_->Stop(); + return -1; + } + + INTELL_VOICE_LOG_INFO("exit"); + return 0; +} + +int32_t EnrollEngine::Stop() +{ + StopAudioSource(); + + return EngineBase::Stop(); +} + +int32_t EnrollEngine::SetParameter(const std::string &keyValueList) +{ + if (SetParameterInner(keyValueList)) { + INTELL_VOICE_LOG_INFO("inner parameter"); + return 0; + } + + return EngineBase::SetParameter(keyValueList); +} + +bool EnrollEngine::SetParameterInner(const std::string &keyValueList) +{ + std::lock_guard lock(mutex_); + + const std::unique_ptr &historyInfoMgr = + IntellVoiceServiceManager::GetInstance()->GetHistoryInfoMgr(); + if (historyInfoMgr == nullptr) { + INTELL_VOICE_LOG_ERROR("historyInfoMgr is nullptr"); + return false; + } + + std::map kvpairs; + SplitStringToKVPair(keyValueList, kvpairs); + for (auto it : kvpairs) { + if (it.first == std::string("wakeup_bundle_name")) { + INTELL_VOICE_LOG_INFO("set wakeup bundle name:%{public}s", it.second.c_str()); + historyInfoMgr->SetWakeupEngineBundleName(it.second); + return true; + } + if (it.first == std::string("wakeup_ability_name")) { + INTELL_VOICE_LOG_INFO("set wakeup ability name:%{public}s", it.second.c_str()); + historyInfoMgr->SetWakeupEngineAbilityName(it.second); + return true; + } + } + + return false; +} + +void EnrollEngine::WriteBufferFromAshmem(uint8_t *&buffer, uint32_t size, sptr ashmem) +{ + if (!ashmem->MapReadOnlyAshmem()) { + INTELL_VOICE_LOG_ERROR("map ashmem failed"); + return; + } + + const uint8_t *tmpBuffer = static_cast(ashmem->ReadFromAshmem(size, 0)); + if (tmpBuffer == nullptr) { + INTELL_VOICE_LOG_ERROR("read from ashmem failed"); + return; + } + + buffer = new (std::nothrow) uint8_t[size]; + if (buffer == nullptr) { + INTELL_VOICE_LOG_ERROR("allocate buffer failed"); + return; + } + + if (memcpy_s(buffer, size, tmpBuffer, size) != 0) { + INTELL_VOICE_LOG_ERROR("memcpy_s failed"); + return; + } +} + +void EnrollEngine::ProcDspModel() +{ + uint8_t *buffer = nullptr; + uint32_t size = 0; + sptr ashmem; + adapter_->Read(DSP_MODLE, ashmem); + if (ashmem == nullptr) { + INTELL_VOICE_LOG_ERROR("ashmem is nullptr"); + return; + } + + ON_SCOPE_EXIT_WITH_NAME(ashmemExit) + { + INTELL_VOICE_LOG_DEBUG("close ashmem"); + ashmem->UnmapAshmem(); + ashmem->CloseAshmem(); + }; + + size = static_cast(ashmem->GetAshmemSize()); + if (size == 0) { + INTELL_VOICE_LOG_ERROR("size is zero"); + return; + } + + WriteBufferFromAshmem(buffer, size, ashmem); + if (buffer == nullptr) { + INTELL_VOICE_LOG_ERROR("buffer is nullptr"); + return; + } + + ON_SCOPE_EXIT_WITH_NAME(bufferExit) + { + INTELL_VOICE_LOG_DEBUG("now delete buffer"); + delete[] buffer; + buffer = nullptr; + }; + + std::shared_ptr model = std::make_shared( + (IntellVoiceServiceManager::GetEnrollModelUuid()), 1); + if (model == nullptr) { + INTELL_VOICE_LOG_ERROR("model is null"); + return; + } + + model->SetData(buffer, size); + auto triggerMgr = TriggerManager::GetInstance(); + if (triggerMgr == nullptr) { + INTELL_VOICE_LOG_ERROR("trigger manager is nullptr"); + return; + } + triggerMgr->UpdateModel(model); +} + +bool EnrollEngine::StartAudioSource() +{ + auto listener = std::make_unique([&] (uint8_t *buffer, uint32_t size) { + if (adapter_ != nullptr) { + std::vector audioBuff(&buffer[0], &buffer[size]); + adapter_->WriteAudio(audioBuff); + }}, [&] (bool isError) + { + INTELL_VOICE_LOG_INFO("end of pcm, isError:%d", isError); + if ((adapter_ != nullptr) && (!isError)) { + adapter_->SetParameter("end_of_pcm=true"); + } + }); + if (listener == nullptr) { + INTELL_VOICE_LOG_ERROR("create listener failed"); + return false; + } + + audioSource_ = std::make_unique(MIN_BUFFER_SIZE, INTERVAL, std::move(listener), + capturerOptions_); + if (audioSource_ == nullptr) { + INTELL_VOICE_LOG_ERROR("create audio source failed"); + return false; + } + + if (!audioSource_->Start()) { + INTELL_VOICE_LOG_ERROR("start capturer failed"); + audioSource_ = nullptr; + return false; + } + + return true; +} + +void EnrollEngine::StopAudioSource() +{ + std::lock_guard lock(mutex_); + INTELL_VOICE_LOG_INFO("enter"); + if (audioSource_ != nullptr) { + audioSource_->Stop(); + audioSource_ = nullptr; + } +} +} +} \ No newline at end of file diff --git a/services/intell_voice_engine/server/enroll/enroll_engine.h b/services/intell_voice_engine/server/enroll/enroll_engine.h new file mode 100755 index 0000000..4d6f999 --- /dev/null +++ b/services/intell_voice_engine/server/enroll/enroll_engine.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef ENROLL_ENGINE_H +#define ENROLL_ENGINE_H +#include +#include +#include +#include "engine_base.h" +#include "v1_0/iintell_voice_engine_callback.h" +#include "audio_info.h" +#include "audio_source.h" +#include "intell_voice_generic_factory.h" + +namespace OHOS { +namespace IntellVoiceEngine { +class EnrollEngine : public EngineBase { +public: + ~EnrollEngine(); + virtual bool Init() override; + void SetCallback(sptr object) override; + int32_t Attach(const IntellVoiceEngineInfo &info) override; + int32_t Detach(void) override; + int32_t Start(bool isLast) override; + int32_t Stop() override; + int32_t SetParameter(const std::string &keyValueList) override; + +private: + EnrollEngine(); + bool SetParameterInner(const std::string &keyValueList); + bool StartAudioSource(); + void StopAudioSource(); + void OnEnrollEvent(int32_t msgId, int32_t result); + void OnEnrollComplete(); + void ProcDspModel(); + void WriteBufferFromAshmem(uint8_t *&buffer, uint32_t size, sptr ashmem); + +private: + std::string name_ = "lp enroll engine instance"; + bool isPcmFromExternal_ = false; + int32_t enrollResult_ = -1; + sptr callback_ = nullptr; + OHOS::AudioStandard::AudioCapturerOptions capturerOptions_; + std::unique_ptr audioSource_ = nullptr; + friend class IntellVoiceUtils::SptrFactory; +}; +} +} +#endif diff --git a/services/intell_voice_engine/server/sa/intell_voice_engine_callback_proxy.cpp b/services/intell_voice_engine/server/sa/intell_voice_engine_callback_proxy.cpp new file mode 100755 index 0000000..56c109c --- /dev/null +++ b/services/intell_voice_engine/server/sa/intell_voice_engine_callback_proxy.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "intell_voice_engine_callback_proxy.h" +#include "intell_voice_log.h" + +#define LOG_TAG "IntellVoiceEngineCallbackProxy" + +using namespace OHOS::HDI::IntelligentVoice::Engine::V1_0; + +namespace OHOS { +namespace IntellVoiceEngine { +void IntellVoiceEngineCallbackProxy::OnIntellVoiceEngineEvent(const IntellVoiceEngineCallBackEvent &event) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + INTELL_VOICE_LOG_INFO("enter"); + + if (!data.WriteInterfaceToken(IIntelligentVoiceEngineCallback::GetDescriptor())) { + INTELL_VOICE_LOG_ERROR("WriteInterfaceToken failed"); + return; + } + + if (!data.WriteInt32(static_cast(event.msgId))) { + INTELL_VOICE_LOG_ERROR("write msgid failed"); + return; + } + + if (!data.WriteInt32(static_cast(event.result))) { + INTELL_VOICE_LOG_ERROR("write result failed"); + return; + } + + if (!data.WriteString(event.info)) { + INTELL_VOICE_LOG_ERROR("write info failed"); + return; + } + + int32_t error = Remote()->SendRequest(IIntelligentVoiceEngineCallback::Code::ON_INTELL_VOICE_ENGINE_EVENT, + data, reply, option); + if (error != 0) { + INTELL_VOICE_LOG_ERROR("send request error: %{public}d", error); + } + reply.ReadInt32(); +} +} +} \ No newline at end of file diff --git a/services/intell_voice_engine/server/sa/intell_voice_engine_callback_proxy.h b/services/intell_voice_engine/server/sa/intell_voice_engine_callback_proxy.h new file mode 100755 index 0000000..c0eddbc --- /dev/null +++ b/services/intell_voice_engine/server/sa/intell_voice_engine_callback_proxy.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef ENGINE_CALLBACK_PROXY_H +#define ENGINE_CALLBACK_PROXY_H + +#include "iremote_proxy.h" +#include "i_intell_voice_engine_callback.h" + +namespace OHOS { +namespace IntellVoiceEngine { +using OHOS::HDI::IntelligentVoice::Engine::V1_0::IntellVoiceEngineCallBackEvent; + +class IntellVoiceEngineCallbackProxy : public IRemoteProxy { +public: + explicit IntellVoiceEngineCallbackProxy(const sptr &impl) + : IRemoteProxy(impl) {}; + virtual ~IntellVoiceEngineCallbackProxy() = default; + void OnIntellVoiceEngineEvent(const IntellVoiceEngineCallBackEvent &event) override; +private: + static inline BrokerDelegator delegator_; +}; +} +} +#endif \ No newline at end of file diff --git a/services/intell_voice_engine/server/sa/intell_voice_engine_stub.cpp b/services/intell_voice_engine/server/sa/intell_voice_engine_stub.cpp new file mode 100755 index 0000000..d03f089 --- /dev/null +++ b/services/intell_voice_engine/server/sa/intell_voice_engine_stub.cpp @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "intell_voice_engine_stub.h" +#include "securec.h" +#include "intell_voice_log.h" + +#define LOG_TAG "IntellVoiceEngineStub" + +namespace OHOS { +namespace IntellVoiceEngine { +int32_t IntellVoiceEngineStub::OnRemoteRequest(uint32_t code, + MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + if (data.ReadInterfaceToken() != IIntellVoiceEngine::GetDescriptor()) { + INTELL_VOICE_LOG_ERROR("token mismatch"); + return -1; + } + + int32_t ret = 0; + + switch (code) { + case INTELL_VOICE_ENGINE_SET_CALLBACK: + object = data.ReadRemoteObject(); + SetCallback(object); + break; + case INTELL_VOICE_ENGINE_ATTACH: + info.wakeupPhrase = data.ReadString(); + info.isPcmFromExternal = data.ReadBool(); + info.minBufSize = data.ReadInt32(); + info.sampleChannels = data.ReadInt32(); + info.bitsPerSample = data.ReadInt32(); + info.sampleRate = data.ReadInt32(); + ret = Attach(info); + break; + case INTELL_VOICE_ENGINE_DETACH: + ret = Detach(); + break; + case INTELL_VOICE_ENGINE_SET_PARAMETER: + ret = SetParameter(data.ReadString()); + break; + case INTELL_VOICE_ENGINE_GET_PARAMETER: + str = GetParameter(data.ReadString()); + reply.WriteString(str); + break; + case INTELL_VOICE_ENGINE_START: + ret = Start(data.ReadBool()); + break; + case INTELL_VOICE_ENGINE_STOP: + ret = Stop(); + break; + case INTELL_VOICE_ENGINE_WRITE_AUDIO: + size = data.ReadInt32(); + buffer = data.ReadBuffer(size); + ret = WriteAudio(buffer, size); + break; + default: + ret = IPCObjectStub::OnRemoteRequest(code, data, reply, option); + break; + } + + return ret; +} +} +} \ No newline at end of file diff --git a/services/intell_voice_engine/server/sa/intell_voice_engine_stub.h b/services/intell_voice_engine/server/sa/intell_voice_engine_stub.h new file mode 100755 index 0000000..be9e3e0 --- /dev/null +++ b/services/intell_voice_engine/server/sa/intell_voice_engine_stub.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTELL_VOICE_ENGINE_STUB_H +#define INTELL_VOICE_ENGINE_STUB_H +#include "iremote_stub.h" +#include "i_intell_voice_engine.h" +namespace OHOS { +namespace IntellVoiceEngine { +class IntellVoiceEngineStub : public IRemoteStub { +public: + int32_t OnRemoteRequest(uint32_t code, + MessageParcel &data, MessageParcel &reply, MessageOption &option) override; +private: + sptr object; + IntellVoiceEngineInfo info; + std::string str; + int size = 0; + const uint8_t *buffer; +}; +} +} +#endif diff --git a/services/intell_voice_engine/server/sa/intell_voice_service.cpp b/services/intell_voice_engine/server/sa/intell_voice_service.cpp new file mode 100755 index 0000000..ff8fcda --- /dev/null +++ b/services/intell_voice_engine/server/sa/intell_voice_service.cpp @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "intell_voice_service.h" + +#include +#include +#include +#include +#include "accesstoken_kit.h" +#include "ipc_skeleton.h" +#include "intell_voice_log.h" +#include "system_ability_definition.h" +#include "intell_voice_service_manager.h" +#include "common_event_manager.h" +#include "common_event_support.h" + +using namespace std; +using namespace OHOS::AppExecFwk; +using namespace OHOS::EventFwk; +#define LOG_TAG "IntellVoiceService" + +namespace OHOS { +namespace IntellVoiceEngine { +REGISTER_SYSTEM_ABILITY_BY_ID(IntellVoiceService, INTELL_VOICE_SERVICE_ID, true); +const std::string OHOS_PERMISSION_INTELL_VOICE = "ohos.permission.MANAGE_INTELLIGENT_VOICE"; + +IntellVoiceService::IntellVoiceService(int32_t systemAbilityId, bool runOnCreate) + : SystemAbility(INTELL_VOICE_SERVICE_ID, true) +{ +} + +IntellVoiceService::~IntellVoiceService() +{ +} + +int32_t IntellVoiceService::CreateIntellVoiceEngine(IntellVoiceEngineType type, sptr &inst) +{ + if (!VerifyClientPermission(OHOS_PERMISSION_INTELL_VOICE)) { + INTELL_VOICE_LOG_WARN("verify permission"); + } + + INTELL_VOICE_LOG_INFO("enter, type: %{public}d", type); + std::unique_ptr &mgr = IntellVoiceServiceManager::GetInstance(); + if (mgr == nullptr) { + INTELL_VOICE_LOG_ERROR("mgr is nullptr"); + return -1; + } + + inst = mgr->CreateEngine(type); + if (inst == nullptr) { + INTELL_VOICE_LOG_ERROR("engine is nullptr"); + return -1; + } + INTELL_VOICE_LOG_INFO("create engine ok"); + return 0; +} + +int32_t IntellVoiceService::ReleaseIntellVoiceEngine(IntellVoiceEngineType type) +{ + INTELL_VOICE_LOG_INFO("enter, type: %{public}d", type); + std::unique_ptr &mgr = IntellVoiceServiceManager::GetInstance(); + if (mgr == nullptr) { + INTELL_VOICE_LOG_ERROR("mgr is nullptr"); + return -1; + } + return mgr->ReleaseEngine(type); +} + +void IntellVoiceService::OnStart(void) +{ + bool ret = Publish(this); + if (!ret) { + INTELL_VOICE_LOG_ERROR("publish failed!"); + return; + } + CreateSystemEventObserver(); + AddSystemAbilityListener(COMMON_EVENT_SERVICE_ID); + AddSystemAbilityListener(DISTRIBUTED_KV_DATA_SERVICE_ABILITY_ID); + RegisterPermissionCallback(OHOS_PERMISSION_INTELL_VOICE); + INTELL_VOICE_LOG_INFO("publish ok"); +} + +void IntellVoiceService::OnStop(void) +{ + const auto &manager = IntellVoiceServiceManager::GetInstance(); + if (manager != nullptr) { + manager->ReleaseSwitchProvider(); + } + + if (systemEventObserver_ != nullptr) { + systemEventObserver_->Unsubscribe(); + } +} + +void IntellVoiceService::OnAddSystemAbility(int32_t systemAbilityId, const std::string &deviceId) +{ + INTELL_VOICE_LOG_INFO("systemAbilityId:%{public}d", systemAbilityId); + if (systemAbilityId == COMMON_EVENT_SERVICE_ID) { + if (systemEventObserver_ != nullptr) { + systemEventObserver_->Subscribe(); + } + } else if (systemAbilityId == DISTRIBUTED_KV_DATA_SERVICE_ABILITY_ID) { + const auto &manager = IntellVoiceServiceManager::GetInstance(); + if (manager != nullptr) { + manager->CreateSwitchProvider(); + } + } else { + INTELL_VOICE_LOG_WARN("unhandled sysabilityId"); + } +} + +void IntellVoiceService::OnRemoveSystemAbility(int32_t systemAbilityId, const std::string &deviceId) +{} + +void IntellVoiceService::CreateSystemEventObserver() +{ + std::shared_ptr runner = EventRunner::Create("service"); + if (runner == nullptr) { + INTELL_VOICE_LOG_ERROR("runner is null"); + return; + } + + std::shared_ptr handler = std::make_shared(runner); + if (handler == nullptr) { + INTELL_VOICE_LOG_ERROR("handler is null"); + return; + } + + OHOS::EventFwk::MatchingSkills matchingSkills; + matchingSkills.AddEvent(OHOS::EventFwk::CommonEventSupport::COMMON_EVENT_SCREEN_ON); + matchingSkills.AddEvent(OHOS::EventFwk::CommonEventSupport::COMMON_EVENT_SCREEN_OFF); + matchingSkills.AddEvent(OHOS::EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_DATA_CLEARED); + matchingSkills.AddEvent(OHOS::EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_REPLACED); + matchingSkills.AddEvent(OHOS::EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_REMOVED); + OHOS::EventFwk::CommonEventSubscribeInfo subscribeInfo(matchingSkills); + systemEventObserver_ = SystemEventObserver::Create(subscribeInfo); + if (systemEventObserver_ == nullptr) { + INTELL_VOICE_LOG_ERROR("systemEventObserver_ is nullptr"); + return; + } + systemEventObserver_->SetEventHandler(handler); + INTELL_VOICE_LOG_INFO("create system event observer successfully"); +} + +static void print_to_file(void *fp, const char *s) +{ + (void)fputs(s, (FILE *)fp); +} + +int IntellVoiceService::Dump(int fd, const std::vector &args) +{ + FILE* fp = fdopen(fd, "w+"); + if (fp != nullptr) { + malloc_stats_print(print_to_file, fp, ""); + fp = nullptr; + } + return 0; +} + +bool IntellVoiceService::VerifyClientPermission(const std::string &permissionName) +{ + Security::AccessToken::AccessTokenID clientTokenId = IPCSkeleton::GetCallingTokenID(); + INTELL_VOICE_LOG_INFO("clientTokenId:%{public}d", clientTokenId); + int res = Security::AccessToken::AccessTokenKit::VerifyAccessToken(clientTokenId, permissionName); + if (res != Security::AccessToken::PermissionState::PERMISSION_GRANTED) { + INTELL_VOICE_LOG_ERROR("Permission denied!"); + return false; + } + return true; +} + +void IntellVoiceService::RegisterPermissionCallback(const std::string &permissionName) +{ + INTELL_VOICE_LOG_INFO("enter"); + Security::AccessToken::PermStateChangeScope scopeInfo; + scopeInfo.permList = {permissionName}; + auto callbackPtr = std::make_shared(scopeInfo); + int32_t res = Security::AccessToken::AccessTokenKit::RegisterPermStateChangeCallback(callbackPtr); + if (res < 0) { + INTELL_VOICE_LOG_ERROR("fail to call RegisterPermStateChangeCallback."); + } +} + +void IntellVoiceService::PerStateChangeCbCustomizeCallback::PermStateChangeCallback( + Security::AccessToken::PermStateChangeInfo& result) +{ + INTELL_VOICE_LOG_INFO("enter, permStateChangeType: %{public}d", result.permStateChangeType); + if (result.permStateChangeType == 0) { + INTELL_VOICE_LOG_ERROR("The permission is canceled."); + } +} +} // namespace IntellVoiceEngine +} // namespace OHOS \ No newline at end of file diff --git a/services/intell_voice_engine/server/sa/intell_voice_service.h b/services/intell_voice_engine/server/sa/intell_voice_service.h new file mode 100755 index 0000000..ca0b399 --- /dev/null +++ b/services/intell_voice_engine/server/sa/intell_voice_service.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef INTELL_VOICE_SERVICE_H +#define INTELL_VOICE_SERVICE_H +#include +#include "accesstoken_kit.h" +#include "ipc_skeleton.h" +#include "system_ability.h" +#include "intell_voice_service_stub.h" +#include "i_intell_voice_engine.h" +#include "system_event_observer.h" + +#include "trigger_manager.h" + +namespace OHOS { +namespace IntellVoiceEngine { +class IntellVoiceService : public SystemAbility, public IntellVoiceServiceStub { + DECLARE_SYSTEM_ABILITY(IntellVoiceService); +public: + explicit IntellVoiceService(int32_t systemAbilityId, bool runOnCreate = true); + ~IntellVoiceService(); + int32_t CreateIntellVoiceEngine(IntellVoiceEngineType type, sptr &inst) override; + int32_t ReleaseIntellVoiceEngine(IntellVoiceEngineType type) override; + int32_t Dump(int fd, const std::vector &args) override; + + class PerStateChangeCbCustomizeCallback : public Security::AccessToken::PermStateChangeCallbackCustomize { + public: + explicit PerStateChangeCbCustomizeCallback(const Security::AccessToken::PermStateChangeScope &scopeInfo) + : PermStateChangeCallbackCustomize(scopeInfo) {} + ~PerStateChangeCbCustomizeCallback() {} + + void PermStateChangeCallback(Security::AccessToken::PermStateChangeInfo& result) override; + }; + +protected: + void OnStart() override; + void OnStop() override; + void OnAddSystemAbility(int32_t systemAbilityId, const std::string& deviceId) override; + void OnRemoveSystemAbility(int32_t systemAbilityId, const std::string& deviceId) override; +private: + void CreateSystemEventObserver(); + bool VerifyClientPermission(const std::string &permissionName); + void RegisterPermissionCallback(const std::string &permissionName); + +private: + std::shared_ptr systemEventObserver_ = nullptr; +}; +} +} +#endif diff --git a/services/intell_voice_engine/server/sa/intell_voice_service_manager.cpp b/services/intell_voice_engine/server/sa/intell_voice_service_manager.cpp new file mode 100755 index 0000000..2e74d54 --- /dev/null +++ b/services/intell_voice_engine/server/sa/intell_voice_service_manager.cpp @@ -0,0 +1,368 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "intell_voice_service_manager.h" + +#include "intell_voice_log.h" +#include "engine_factory.h" +#include "wakeup_engine.h" +#include "trigger_manager.h" +#include "intell_voice_generic_factory.h" +#include "trigger_detector_callback.h" +#include "memory_guard.h" + +using namespace OHOS::IntellVoiceTrigger; +using namespace OHOS::IntellVoiceUtils; +#define LOG_TAG "IntellVoiceServiceManager" + +namespace OHOS { +namespace IntellVoiceEngine { +const int32_t IntellVoiceServiceManager::g_enrollModelUuid = 1; + +std::unique_ptr IntellVoiceServiceManager::g_intellVoiceServiceMgr = + std::unique_ptr(new (std::nothrow) IntellVoiceServiceManager()); + +IntellVoiceServiceManager::IntellVoiceServiceManager() +{ + OHOS::IntellVoiceUtils::MemoryGuard memoryGuard; + historyInfoMgr_ = std::make_unique(); + if (historyInfoMgr_ == nullptr) { + INTELL_VOICE_LOG_ERROR("historyInfoMgr_ is nullptr"); + } +} + +IntellVoiceServiceManager::~IntellVoiceServiceManager() +{ + engines_.clear(); + switchObserver_ = nullptr; + switchProvider_ = nullptr; +} + +std::unique_ptr &IntellVoiceServiceManager::GetInstance() +{ + return g_intellVoiceServiceMgr; +} + +sptr IntellVoiceServiceManager::CreateEngine(IntellVoiceEngineType type) +{ + INTELL_VOICE_LOG_INFO("enter, type:%{public}d", type); + if (type == INTELL_VOICE_ENROLL) { + StopDetection(); + } + + std::lock_guard lock(engineMutex_); + + if (ApplyArbitration(type, ENGINE_EVENT_CREATE) != ARBITRATION_OK) { + INTELL_VOICE_LOG_ERROR("policy manager reject create engine, type:%{public}d", type); + return nullptr; + } + + return CreateEngineInner(type); +} + +sptr IntellVoiceServiceManager::CreateEngineInner(IntellVoiceEngineType type) +{ + INTELL_VOICE_LOG_INFO("create engine enter, type: %d", type); + OHOS::IntellVoiceUtils::MemoryGuard memoryGuard; + auto it = engines_.find(type); + if (it != engines_.end() && it->second != nullptr) { + return it->second; + } + + sptr engine = EngineFactory::CreateEngineInst(type); + if (engine == nullptr) { + INTELL_VOICE_LOG_ERROR("create engine failed, type:%{public}d", type); + return nullptr; + } + + engines_[type] = engine; + INTELL_VOICE_LOG_INFO("create engine ok"); + return engine; +} + +int32_t IntellVoiceServiceManager::ReleaseEngine(IntellVoiceEngineType type) +{ + INTELL_VOICE_LOG_INFO("enter, type:%{public}d", type); + std::lock_guard lock(engineMutex_); + auto ret = ReleaseEngineInner(type); + if (ret != 0) { + return ret; + } + + if (type == INTELL_VOICE_ENROLL) { + auto triggerMgr = TriggerManager::GetInstance(); + if (triggerMgr == nullptr) { + INTELL_VOICE_LOG_WARN("trigger manager is nullptr"); + return 0; + } + auto model = triggerMgr->GetModel(IntellVoiceServiceManager::GetEnrollModelUuid()); + if (model == nullptr) { + INTELL_VOICE_LOG_WARN("no model"); + return 0; + } + + auto wakeupEngine = CreateEngineInner(INTELL_VOICE_WAKEUP); + if (wakeupEngine == nullptr) { + INTELL_VOICE_LOG_WARN("failed to create wakeup engine"); + return 0; + } + CreateDetector(); + if (switchProvider_->QuerySwitchStatus()) { + StartDetection(); + } + } + + return 0; +} + +int32_t IntellVoiceServiceManager::ReleaseEngineInner(IntellVoiceEngineType type) +{ + OHOS::IntellVoiceUtils::MemoryGuard memoryGuard; + auto it = engines_.find(type); + if (it == engines_.end()) { + INTELL_VOICE_LOG_ERROR("there is no engine(%{public}d) in list", type); + return -1; + } + + it->second = nullptr; + engines_.erase(type); + return 0; +} + +void IntellVoiceServiceManager::CreateSwitchProvider() +{ + switchObserver_ = sptr(new (std::nothrow) SwitchObserver()); + if (switchObserver_ == nullptr) { + INTELL_VOICE_LOG_ERROR("switchObserver_ is nullptr"); + return; + } + + switchObserver_->SetUpdateFunc([]() { + const auto &manager = IntellVoiceServiceManager::GetInstance(); + if (manager != nullptr) { + manager->OnSwitchChange(); + } + }); + + switchProvider_ = UniquePtrFactory::CreateInstance(); + if (switchProvider_ == nullptr) { + INTELL_VOICE_LOG_ERROR("switchProvider_ is nullptr"); + return; + } + + if (switchObserver_ != nullptr) { + switchProvider_->RegisterObserver(switchObserver_); + } +} + +void IntellVoiceServiceManager::ReleaseSwitchProvider() +{ + if (switchProvider_ == nullptr) { + INTELL_VOICE_LOG_ERROR("switchProvider_ is nullptr"); + return; + } + + if (switchObserver_ != nullptr) { + switchProvider_->UnregisterObserver(switchObserver_); + } + + switchProvider_ = nullptr; +} + +void IntellVoiceServiceManager::CreateDetector() +{ + std::lock_guard lock(detectorMutex_); + if (detector_ != nullptr) { + INTELL_VOICE_LOG_INFO("detector is already existed, no need to create"); + return; + } + + std::shared_ptr cb = std::make_shared([&]() { OnDetected(); }); + if (cb == nullptr) { + INTELL_VOICE_LOG_ERROR("cb is nullptr"); + return; + } + + auto triggerMgr = TriggerManager::GetInstance(); + if (triggerMgr == nullptr) { + INTELL_VOICE_LOG_ERROR("trigger manager is nullptr"); + return; + } + + detector_ = triggerMgr->CreateTriggerDetector(1, cb); + if (detector_ == nullptr) { + INTELL_VOICE_LOG_ERROR("detector_ is nullptr"); + return; + } +} + +void IntellVoiceServiceManager::StartDetection() +{ + std::lock_guard lock(detectorMutex_); + if (detector_ == nullptr) { + INTELL_VOICE_LOG_ERROR("detector_ is nullptr"); + return; + } + + detector_->StartRecognition(); +} + +void IntellVoiceServiceManager::StopDetection() +{ + std::lock_guard lock(detectorMutex_); + if (detector_ == nullptr) { + return; + } + + detector_->StopRecognition(); +} + +void IntellVoiceServiceManager::OnDetected() +{ + sptr engine = nullptr; + + { + std::lock_guard lock(engineMutex_); + auto it = engines_.find(INTELL_VOICE_WAKEUP); + if ((it == engines_.end()) || (it->second == nullptr)) { + INTELL_VOICE_LOG_ERROR("wakeup engine is not existed"); + return; + } + + engine = it->second; + } + + engine->OnDetected(); +} + +void IntellVoiceServiceManager::OnUserUnlock() +{ + auto triggerMgr = TriggerManager::GetInstance(); + if (triggerMgr == nullptr) { + INTELL_VOICE_LOG_ERROR("trigger manager is nullptr"); + return; + } + auto model = triggerMgr->GetModel(IntellVoiceServiceManager::GetEnrollModelUuid()); + if (model == nullptr) { + INTELL_VOICE_LOG_INFO("no model"); + return; + } + + { + std::lock_guard lock(engineMutex_); + sptr wakeupEngine = EngineFactory::CreateEngineInst(INTELL_VOICE_WAKEUP); + if (wakeupEngine == nullptr) { + INTELL_VOICE_LOG_ERROR("wakeupEngine is nullptr"); + return; + } + engines_[INTELL_VOICE_WAKEUP] = wakeupEngine; + } + + CreateDetector(); + if (switchProvider_->QuerySwitchStatus()) { + StartDetection(); + } +} + +void IntellVoiceServiceManager::OnSwitchChange() +{ + if (switchProvider_ == nullptr) { + INTELL_VOICE_LOG_ERROR("switchProvider_ is nullptr"); + return; + } + + { + std::lock_guard lock(engineMutex_); + auto it = engines_.find(INTELL_VOICE_ENROLL); + if ((it != engines_.end()) && (it->second != nullptr)) { + INTELL_VOICE_LOG_INFO("enroll engine is existed"); + return; + } + } + + if (switchProvider_->QuerySwitchStatus()) { + INTELL_VOICE_LOG_INFO("switch on"); + StartDetection(); + } else { + INTELL_VOICE_LOG_INFO("switch off"); + StopDetection(); + } +} + +int32_t IntellVoiceServiceManager::ApplyArbitration(IntellVoiceEngineType type, EngineEvent event) +{ + INTELL_VOICE_LOG_INFO("enter"); + switch (event) { + case ENGINE_EVENT_CREATE: + return CreateArbitration(type); + case ENGINE_EVENT_START: + return StartArbitration(type); + default: + INTELL_VOICE_LOG_INFO("unknown engine event:%d", event); + break; + } + return ARBITRATION_OK; +} + +int32_t IntellVoiceServiceManager::CreateArbitration(IntellVoiceEngineType type) +{ + INTELL_VOICE_LOG_INFO("enter"); + if (type == INTELL_VOICE_ENROLL) { + auto wakeupEngineIt = engines_.find(INTELL_VOICE_WAKEUP); + if (wakeupEngineIt != engines_.end()) { + HandlePreemption(wakeupEngineIt->second); + } + + auto enrollEngineIt = engines_.find(INTELL_VOICE_ENROLL); + if (enrollEngineIt != engines_.end()) { + HandleReplace(enrollEngineIt->second); + } + } + return ARBITRATION_OK; +} + +int32_t IntellVoiceServiceManager::StartArbitration(IntellVoiceEngineType type) +{ + INTELL_VOICE_LOG_INFO("enter"); + if (type == INTELL_VOICE_WAKEUP) { + auto it = engines_.find(INTELL_VOICE_ENROLL); + if (it != engines_.end()) { + return ARBITRATION_REJECT; + } + } + return ARBITRATION_OK; +} + +void IntellVoiceServiceManager::HandlePreemption(sptr currentEngine) +{ + INTELL_VOICE_LOG_INFO("enter"); + if (currentEngine == nullptr) { + INTELL_VOICE_LOG_ERROR("failed to stop current engine, current engine is null"); + return; + } + currentEngine->Stop(); +} + +void IntellVoiceServiceManager::HandleReplace(sptr currentEngine) +{ + INTELL_VOICE_LOG_INFO("enter"); + if (currentEngine == nullptr) { + INTELL_VOICE_LOG_ERROR("failed to detach current engine, current engine is null"); + return; + } + currentEngine->Detach(); + currentEngine = nullptr; +} +} // namespace IntellVoiceEngine +} // namespace OHOS diff --git a/services/intell_voice_engine/server/sa/intell_voice_service_manager.h b/services/intell_voice_engine/server/sa/intell_voice_service_manager.h new file mode 100755 index 0000000..93ebbe6 --- /dev/null +++ b/services/intell_voice_engine/server/sa/intell_voice_service_manager.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef SERVICE_MANAGER_H +#define SERVICE_MANAGER_H +#include +#include +#include "engine_base.h" +#include "trigger_detector.h" +#include "switch_observer.h" +#include "switch_provider.h" +#include "history_info_mgr.h" + +namespace OHOS { +namespace IntellVoiceEngine { +enum EngineEvent { + ENGINE_EVENT_CREATE = 0, + ENGINE_EVENT_START, +}; + +enum ArbitrationResult { + ARBITRATION_OK = 0, + ARBITRATION_REJECT, +}; + +class IntellVoiceServiceManager { +public: + ~IntellVoiceServiceManager(); + static std::unique_ptr &GetInstance(); + static int32_t GetEnrollModelUuid() + { + return g_enrollModelUuid; + } + sptr CreateEngine(IntellVoiceEngineType type); + int32_t ReleaseEngine(IntellVoiceEngineType type); + const std::unique_ptr &GetHistoryInfoMgr() + { + return historyInfoMgr_; + } + void OnUserUnlock(); + void CreateSwitchProvider(); + void ReleaseSwitchProvider(); + void StartDetection(); + void StopDetection(); + + int32_t ApplyArbitration(IntellVoiceEngineType type, EngineEvent event); + +private: + IntellVoiceServiceManager(); + void OnSwitchChange(); + void OnDetected(); + void CreateDetector(); + + int32_t CreateArbitration(IntellVoiceEngineType type); + int32_t StartArbitration(IntellVoiceEngineType type); + void HandlePreemption(sptr currentEngine); + void HandleReplace(sptr currentEngine); + + sptr CreateEngineInner(IntellVoiceEngineType type); + int32_t ReleaseEngineInner(IntellVoiceEngineType type); + +private: + static const int32_t g_enrollModelUuid; + static std::unique_ptr g_intellVoiceServiceMgr; + std::mutex engineMutex_; + std::mutex detectorMutex_; + std::map> engines_; + std::shared_ptr detector_ = nullptr; + sptr switchObserver_ = nullptr; + IntellVoiceUtils::UniqueProductType switchProvider_ = + IntellVoiceUtils::UniqueProductType {nullptr, nullptr}; + std::unique_ptr historyInfoMgr_ = nullptr; +}; +} // namespace IntellVoice +} // namespace OHOS +#endif \ No newline at end of file diff --git a/services/intell_voice_engine/server/sa/intell_voice_service_stub.cpp b/services/intell_voice_engine/server/sa/intell_voice_service_stub.cpp new file mode 100755 index 0000000..56ac7e7 --- /dev/null +++ b/services/intell_voice_engine/server/sa/intell_voice_service_stub.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "intell_voice_service_stub.h" +#include "intell_voice_log.h" + +#define LOG_TAG "IntellVoiceServiceStub" + +namespace OHOS { +namespace IntellVoiceEngine { +int32_t IntellVoiceServiceStub::OnRemoteRequest(uint32_t code, + MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + if (data.ReadInterfaceToken() != IIntellVoiceService::GetDescriptor()) { + INTELL_VOICE_LOG_ERROR("token mismatch"); + return -1; + } + + IntellVoiceEngineType type = static_cast(data.ReadInt32()); + int32_t ret = 0; + + sptr engine; + switch (code) { + case HDI_INTELL_VOICE_SERVICE_CREATE_ENGINE: + ret = CreateIntellVoiceEngine(type, engine); + reply.WriteRemoteObject(engine->AsObject()); + return ret; + + case HDI_INTELL_VOICE_SERVICE_RELEASE_ENGINE: + return ReleaseIntellVoiceEngine(type); + default: + return IPCObjectStub::OnRemoteRequest(code, data, reply, option); + } +} +} +} diff --git a/services/intell_voice_engine/server/sa/intell_voice_service_stub.h b/services/intell_voice_engine/server/sa/intell_voice_service_stub.h new file mode 100755 index 0000000..02471f0 --- /dev/null +++ b/services/intell_voice_engine/server/sa/intell_voice_service_stub.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTELL_VOICE_SERVICE_STUB_H +#define INTELL_VOICE_SERVICE_STUB_H +#include "iremote_stub.h" +#include "i_intell_voice_service.h" + +namespace OHOS { +namespace IntellVoiceEngine { +class IntellVoiceServiceStub : public IRemoteStub { +public: + int32_t OnRemoteRequest(uint32_t code, + MessageParcel &data, MessageParcel &reply, MessageOption &option) override; +}; +} +} +#endif diff --git a/services/intell_voice_engine/server/utils/history_info_mgr.cpp b/services/intell_voice_engine/server/utils/history_info_mgr.cpp new file mode 100755 index 0000000..d36d0a5 --- /dev/null +++ b/services/intell_voice_engine/server/utils/history_info_mgr.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "history_info_mgr.h" + +#include "string_util.h" + +using namespace OHOS::IntellVoiceUtils; +#define LOG_TAG "HistoryInfoMgr" + +namespace OHOS { +namespace IntellVoiceEngine { +constexpr int decimalNotation = 10; +const std::string KEY_ENROLL_ENGINE_UID = "EnrollEngineUid"; +const std::string KEY_WAKEUP_ENGINE_BUNDLE_NAME = "WakeupEngineBundleName"; +const std::string KEY_WAKEUP_ENGINE_ABILITY_NAME = "WakeupEngineAbilityName"; + +HistoryInfoMgr::HistoryInfoMgr() + : ServiceDbHelper("intell_voice_service_manager", "local_intell_voice_history_mgr_storeId") +{ +} + +void HistoryInfoMgr::SetEnrollEngineUid(int32_t uid) +{ + SetValue(KEY_ENROLL_ENGINE_UID, StringUtil::Int2String(uid)); +} + +int32_t HistoryInfoMgr::GetEnrollEngineUid() +{ + std::string value = GetValue(KEY_ENROLL_ENGINE_UID); + return static_cast(strtol(value.c_str(), nullptr, decimalNotation)); +} + +void HistoryInfoMgr::SetWakeupEngineBundleName(std::string bundleName) +{ + SetValue(KEY_WAKEUP_ENGINE_BUNDLE_NAME, bundleName); +} + +std::string HistoryInfoMgr::GetWakeupEngineBundleName() +{ + return GetValue(KEY_WAKEUP_ENGINE_BUNDLE_NAME); +} + +void HistoryInfoMgr::SetWakeupEngineAbilityName(std::string abilityName) +{ + SetValue(KEY_WAKEUP_ENGINE_ABILITY_NAME, abilityName); +} + +std::string HistoryInfoMgr::GetWakeupEngineAbilityName() +{ + return GetValue(KEY_WAKEUP_ENGINE_ABILITY_NAME); +} +} +} \ No newline at end of file diff --git a/services/intell_voice_engine/server/utils/history_info_mgr.h b/services/intell_voice_engine/server/utils/history_info_mgr.h new file mode 100755 index 0000000..83d5a51 --- /dev/null +++ b/services/intell_voice_engine/server/utils/history_info_mgr.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HISTORY_INFO_MGR_H +#define HISTORY_INFO_MGR_H + +#include "service_db_helper.h" +#include "nocopyable.h" + +namespace OHOS { +namespace IntellVoiceEngine { +class HistoryInfoMgr : private ServiceDbHelper { +public: + HistoryInfoMgr(); + ~HistoryInfoMgr() = default; + + void SetEnrollEngineUid(int32_t uid); + int32_t GetEnrollEngineUid(); + void SetWakeupEngineBundleName(std::string bundleName); + std::string GetWakeupEngineBundleName(); + void SetWakeupEngineAbilityName(std::string abilityName); + std::string GetWakeupEngineAbilityName(); + +private: + DISALLOW_COPY_AND_MOVE(HistoryInfoMgr); +}; +} +} +#endif \ No newline at end of file diff --git a/services/intell_voice_engine/server/utils/service_db_helper.cpp b/services/intell_voice_engine/server/utils/service_db_helper.cpp new file mode 100755 index 0000000..6dccb5a --- /dev/null +++ b/services/intell_voice_engine/server/utils/service_db_helper.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "service_db_helper.h" +#include "intell_voice_log.h" + +using namespace OHOS::DistributedKv; +#define LOG_TAG "ServiceDbHelper" + +namespace OHOS { +namespace IntellVoiceEngine { +ServiceDbHelper::ServiceDbHelper(const std::string &inAppId, const std::string &inStoreId) +{ + AppId appId = { inAppId }; + StoreId storeId = { inStoreId }; + + Options options = { + .createIfMissing = true, + .encrypt = false, + .autoSync = true, + .securityLevel = SecurityLevel::S1, + .area = Area::EL1, + .kvStoreType = KvStoreType::SINGLE_VERSION, + .baseDir = "/data/service/el1/public/database/" + appId.appId + }; + + INTELL_VOICE_LOG_INFO("inAppId:%{public}s, inStoreId:%{public}s, options.baseDir:%{public}s", + inAppId.c_str(), appId.appId.c_str(), options.baseDir.c_str()); + + DistributedKvDataManager manager; + Status status = manager.GetSingleKvStore(options, appId, storeId, kvStore_); + if (status != Status::SUCCESS) { + INTELL_VOICE_LOG_INFO("GetSingleKvStore failed, status: %{public}d.", status); + } else { + INTELL_VOICE_LOG_INFO("GetSingleKvStore success"); + } +} + +ServiceDbHelper::~ServiceDbHelper() +{ + kvStore_ = nullptr; +} + +void ServiceDbHelper::SetValue(const std::string &key, const std::string &value) +{ + if (kvStore_ == nullptr) { + INTELL_VOICE_LOG_ERROR("kvStore_ is nullptr"); + return; + } + kvStore_->Put(key, value); +} + +std::string ServiceDbHelper::GetValue(const std::string &key) +{ + if (kvStore_ == nullptr) { + INTELL_VOICE_LOG_ERROR("kvStore_ is nullptr"); + return ""; + } + Value value; + kvStore_->Get(key, value); + return value.ToString(); +} +} +} diff --git a/services/intell_voice_engine/server/utils/service_db_helper.h b/services/intell_voice_engine/server/utils/service_db_helper.h new file mode 100755 index 0000000..c84806e --- /dev/null +++ b/services/intell_voice_engine/server/utils/service_db_helper.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef INTELL_VOICE_SERVICE_DB_HELPER_H +#define INTELL_VOICE_SERVICE_DB_HELPER_H + +#include "distributed_kv_data_manager.h" + +namespace OHOS { +namespace IntellVoiceEngine { +class ServiceDbHelper { +public: + ServiceDbHelper(const std::string &inAppId, const std::string &inStoreId); + ~ServiceDbHelper(); + + void SetValue(const std::string &key, const std::string &value); + std::string GetValue(const std::string &key); + +private: + std::shared_ptr kvStore_ = nullptr; +}; +} +} +#endif \ No newline at end of file diff --git a/services/intell_voice_engine/server/utils/switch_observer.cpp b/services/intell_voice_engine/server/utils/switch_observer.cpp new file mode 100755 index 0000000..cfcc008 --- /dev/null +++ b/services/intell_voice_engine/server/utils/switch_observer.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "switch_observer.h" +#include "intell_voice_log.h" + +#define LOG_TAG "SwitchObserver" + +namespace OHOS { +namespace IntellVoiceEngine { +void SwitchObserver::OnChange() +{ + INTELL_VOICE_LOG_INFO("OnChange"); + if (update_) { + update_(); + } +} + +void SwitchObserver::SetUpdateFunc(UpdateFunc func) +{ + update_ = func; +} +} // namespace IntellVoice +} // namespace OHOS \ No newline at end of file diff --git a/services/intell_voice_engine/server/utils/switch_observer.h b/services/intell_voice_engine/server/utils/switch_observer.h new file mode 100755 index 0000000..1f555e8 --- /dev/null +++ b/services/intell_voice_engine/server/utils/switch_observer.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef SWITCH_OBSERVER_H +#define SWITCH_OBSERVER_H + +#include +#include "data_ability_observer_stub.h" + +namespace OHOS { +namespace IntellVoiceEngine { +using UpdateFunc = std::function; + +class SwitchObserver : public AAFwk::DataAbilityObserverStub { +public: + SwitchObserver() = default; + virtual ~SwitchObserver() = default; + void OnChange() override; + void SetUpdateFunc(UpdateFunc func); + +private: + UpdateFunc update_ = nullptr; +}; +} // namespace IntellVoice +} // namespace OHOS +#endif \ No newline at end of file diff --git a/services/intell_voice_engine/server/utils/switch_provider.cpp b/services/intell_voice_engine/server/utils/switch_provider.cpp new file mode 100755 index 0000000..f1f9f84 --- /dev/null +++ b/services/intell_voice_engine/server/utils/switch_provider.cpp @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "switch_provider.h" +#include "intell_voice_log.h" +#include "iservice_registry.h" +#include "system_ability_definition.h" + +using namespace OHOS::IntellVoiceUtils; +#define LOG_TAG "SwitchProvider" + +namespace OHOS { +namespace IntellVoiceEngine { +const std::string SWITCH_URI_PROXY = "datashare:///com.ohos.settingsdata/entry/settingsdata/SETTINGSDATA?Proxy=true"; +const std::string SWITCH_KEY = "intell_voice_trigger_enabled"; + +SwitchProvider::SwitchProvider() +{ +} + +SwitchProvider::~SwitchProvider() +{ + helper_ = nullptr; +} + +bool SwitchProvider::Init() +{ + auto saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (saManager == nullptr) { + INTELL_VOICE_LOG_ERROR("saManager is nullptr"); + return false; + } + auto remoteObj = saManager->GetSystemAbility(INTELL_VOICE_SERVICE_ID); + if (remoteObj == nullptr) { + INTELL_VOICE_LOG_ERROR("remoteObj is nullptr"); + return false; + } + + helper_ = DataShare::DataShareHelper::Creator(remoteObj, SWITCH_URI_PROXY); + if (helper_ == nullptr) { + INTELL_VOICE_LOG_ERROR("helper_ is nullptr"); + return false; + } + + return true; +} + +void SwitchProvider::RegisterObserver(const sptr &observer) +{ + auto uri = AssembleUri(SWITCH_KEY); + helper_->RegisterObserver(uri, observer); +} + +void SwitchProvider::UnregisterObserver(const sptr &observer) +{ + auto uri = AssembleUri(SWITCH_KEY); + helper_->UnregisterObserver(uri, observer); +} + +bool SwitchProvider::QuerySwitchStatus() +{ + std::vector columns = {"VALUE"}; + DataShare::DataSharePredicates predicates; + predicates.EqualTo("KEYWORD", SWITCH_KEY); + auto uri = AssembleUri(SWITCH_KEY); + auto resultSet = helper_->Query(uri, predicates, columns); + if (resultSet == nullptr) { + INTELL_VOICE_LOG_ERROR("helper->Query return nullptr"); + return false; + } + + int32_t count; + resultSet->GetRowCount(count); + if (count == 0) { + INTELL_VOICE_LOG_ERROR("not found value"); + return false; + } + const int32_t INDEX = 0; + resultSet->GoToRow(INDEX); + std::string value; + resultSet->GetString(INDEX, value); + resultSet->Close(); + + if (value == "0") { + return false; + } else if (value == "1") { + return true; + } else { + return false; + } +} + +Uri SwitchProvider::AssembleUri(const std::string& key) +{ + Uri uri(SWITCH_URI_PROXY + "&key=" + key); + return uri; +} +} // namespace IntellVoice +} // namespace OHOS \ No newline at end of file diff --git a/services/intell_voice_engine/server/utils/switch_provider.h b/services/intell_voice_engine/server/utils/switch_provider.h new file mode 100755 index 0000000..ea0d217 --- /dev/null +++ b/services/intell_voice_engine/server/utils/switch_provider.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef SWITCH_PROVIDER_H +#define SWITCH_PROVIDER_H + +#include "switch_observer.h" +#include "datashare_helper.h" +#include "intell_voice_generic_factory.h" + +namespace OHOS { +namespace IntellVoiceEngine { +class SwitchProvider { +public: + bool Init(); + void RegisterObserver(const sptr &observer); + void UnregisterObserver(const sptr &observer); + bool QuerySwitchStatus(); + +private: + Uri AssembleUri(const std::string& key); + +private: + SwitchProvider(); + ~SwitchProvider(); + + std::shared_ptr helper_ = nullptr; + friend class IntellVoiceUtils::UniquePtrFactory; +}; +} // namespace IntellVoice +} // namespace OHOS +#endif \ No newline at end of file diff --git a/services/intell_voice_engine/server/utils/system_event_observer.cpp b/services/intell_voice_engine/server/utils/system_event_observer.cpp new file mode 100755 index 0000000..d4d3596 --- /dev/null +++ b/services/intell_voice_engine/server/utils/system_event_observer.cpp @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "system_event_observer.h" +#include "event_handler.h" +#include "common_event_manager.h" +#include "common_event_support.h" +#include "intell_voice_log.h" +#include "intell_voice_service_manager.h" + +using namespace OHOS::AppExecFwk; +using namespace OHOS::EventFwk; +#define LOG_TAG "SystemEventObserver" + +namespace OHOS { +namespace IntellVoiceEngine { +SystemEventObserver::SystemEventObserver(const OHOS::EventFwk::CommonEventSubscribeInfo &subscribeInfo) + : EventFwk::CommonEventSubscriber(subscribeInfo), handler_(nullptr) +{ + INTELL_VOICE_LOG_INFO("SystemEventObserver create"); +} + +SystemEventObserver::~SystemEventObserver() +{ + handler_ = nullptr; +} + +std::shared_ptr SystemEventObserver::Create( + const OHOS::EventFwk::CommonEventSubscribeInfo &subscribeInfo) +{ + return std::shared_ptr(new (std::nothrow) SystemEventObserver(subscribeInfo)); +} + +bool SystemEventObserver::Subscribe() +{ + if (!OHOS::EventFwk::CommonEventManager::SubscribeCommonEvent(GetPtr())) { + INTELL_VOICE_LOG_ERROR("SubscribeCommonEvent occur exception."); + return false; + } + return true; +} + +bool SystemEventObserver::Unsubscribe() +{ + if (!OHOS::EventFwk::CommonEventManager::UnSubscribeCommonEvent(GetPtr())) { + INTELL_VOICE_LOG_ERROR("UnsubscribeCommonEvent occur exception."); + return false; + } + return true; +} + +void SystemEventObserver::SetEventHandler(const std::shared_ptr &handler) +{ + handler_ = handler; +} + +void SystemEventObserver::OnReceiveEvent(const OHOS::EventFwk::CommonEventData &eventData) +{ + INTELL_VOICE_LOG_INFO("enter"); + + const OHOS::AAFwk::Want& want = eventData.GetWant(); + std::string action = want.GetAction(); + if (action.empty()) { + INTELL_VOICE_LOG_ERROR("action is empty"); + return; + } + + if (handler_ == nullptr) { + INTELL_VOICE_LOG_ERROR("handler_ is nullptr"); + return; + } + + INTELL_VOICE_LOG_INFO("action:%{public}s.", action.c_str()); + if (action == OHOS::EventFwk::CommonEventSupport::COMMON_EVENT_SCREEN_ON) { + INTELL_VOICE_LOG_INFO("COMMON_EVENT_SCREEN_ON"); + } else if (action == OHOS::EventFwk::CommonEventSupport::COMMON_EVENT_SCREEN_OFF) { + INTELL_VOICE_LOG_INFO("COMMON_EVENT_SCREEN_OFF"); + } else if (action == OHOS::EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_REMOVED) { + INTELL_VOICE_LOG_INFO("COMMON_EVENT_PACKAGE_REMOVED"); + } else if (action == OHOS::EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_REPLACED) { + INTELL_VOICE_LOG_INFO("COMMON_EVENT_PACKAGE_REPLACED"); + } else if (action == OHOS::EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_DATA_CLEARED) { + INTELL_VOICE_LOG_INFO("COMMON_EVENT_PACKAGE_DATA_CLEARED"); + } else if (action == OHOS::EventFwk::CommonEventSupport::COMMON_EVENT_USER_UNLOCKED) { + INTELL_VOICE_LOG_INFO("COMMON_EVENT_USER_UNLOCKED"); + IntellVoiceServiceManager::GetInstance()->OnUserUnlock(); + } else { + INTELL_VOICE_LOG_INFO("unkonw event"); + } +} +} +} \ No newline at end of file diff --git a/services/intell_voice_engine/server/utils/system_event_observer.h b/services/intell_voice_engine/server/utils/system_event_observer.h new file mode 100755 index 0000000..7a0c299 --- /dev/null +++ b/services/intell_voice_engine/server/utils/system_event_observer.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef SYSTEM_EVENT_OBSERVER_H +#define SYSTEM_EVENT_OBSERVER_H + +#include +#include "common_event_subscriber.h" +#include "event_handler.h" + +namespace OHOS { +namespace IntellVoiceEngine { +class SystemEventObserver : public OHOS::EventFwk::CommonEventSubscriber, + public std::enable_shared_from_this { +public: + ~SystemEventObserver(); + static std::shared_ptr Create(const OHOS::EventFwk::CommonEventSubscribeInfo &subscribeInfo); + std::shared_ptr GetPtr() + { + return shared_from_this(); + } + void OnReceiveEvent(const OHOS::EventFwk::CommonEventData &eventData) override; + void SetEventHandler(const std::shared_ptr &handler); + bool Subscribe(); + bool Unsubscribe(); + +private: + explicit SystemEventObserver(const OHOS::EventFwk::CommonEventSubscribeInfo &subscribeInfo); + + std::shared_ptr handler_ = nullptr; +}; +} +} +#endif \ No newline at end of file diff --git a/services/intell_voice_engine/server/wakeup/wakeup_adapter_listener.cpp b/services/intell_voice_engine/server/wakeup/wakeup_adapter_listener.cpp new file mode 100755 index 0000000..a703710 --- /dev/null +++ b/services/intell_voice_engine/server/wakeup/wakeup_adapter_listener.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "wakeup_adapter_listener.h" + +#include +#include "intell_voice_log.h" + +#define LOG_TAG "WakeupAdapterListener" + +using namespace OHOS::HDI::IntelligentVoice::Engine::V1_0; + +namespace OHOS { +namespace IntellVoiceEngine { +WakeupAdapterListener::WakeupAdapterListener(OnWakeupEventCb wakeupEventCb) : wakeupEventCb_(wakeupEventCb) + +{ + INTELL_VOICE_LOG_INFO("constructor"); +} + +WakeupAdapterListener::~WakeupAdapterListener() +{ + INTELL_VOICE_LOG_INFO("destructor"); +} + +void WakeupAdapterListener::SetCallback(const sptr &cb) +{ + std::lock_guard lock(mutex_); + if (cb == nullptr) { + INTELL_VOICE_LOG_ERROR("cb is nullptr"); + return; + } + cb_ = cb; + if (historyEvent_ != nullptr) { + cb_->OnIntellVoiceEngineEvent(*(historyEvent_.get())); + historyEvent_ = nullptr; + } +} + +void WakeupAdapterListener::OnIntellVoiceHdiEvent(const IntellVoiceEngineCallBackEvent &event) +{ + INTELL_VOICE_LOG_INFO("OnIntellVoiceHdiEvent"); + + { + std::lock_guard lock(mutex_); + if (cb_ == nullptr) { + INTELL_VOICE_LOG_WARN("cb_ is nullptr"); + BackupCallBackEvent(event); + wakeupEventCb_(event.msgId, event.result); + return; + } + + historyEvent_ = nullptr; + } + + if (event.msgId == INTELL_VOICE_ENGINE_MSG_RECOGNIZE_COMPLETE) { + cb_->OnIntellVoiceEngineEvent(event); + } + + wakeupEventCb_(event.msgId, event.result); +} + +void WakeupAdapterListener::BackupCallBackEvent(const IntellVoiceEngineCallBackEvent &event) +{ + if (event.msgId != INTELL_VOICE_ENGINE_MSG_RECOGNIZE_COMPLETE) { + return; + } + + INTELL_VOICE_LOG_INFO("Backup CallBackEvent"); + + historyEvent_ = std::make_shared(); + if (historyEvent_ == nullptr) { + INTELL_VOICE_LOG_INFO("historyEvent_ is nullptr"); + return; + } + + historyEvent_->msgId = event.msgId; + historyEvent_->result = event.result; + historyEvent_->info = event.info; +} +} +} \ No newline at end of file diff --git a/services/intell_voice_engine/server/wakeup/wakeup_adapter_listener.h b/services/intell_voice_engine/server/wakeup/wakeup_adapter_listener.h new file mode 100755 index 0000000..c54ddbb --- /dev/null +++ b/services/intell_voice_engine/server/wakeup/wakeup_adapter_listener.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef WAKEUP_ADAPTER_LISTENER_H +#define WAKEUP_ADAPTER_LISTENER_H + +#include +#include +#include +#include "intell_voice_adapter_listener.h" +#include "i_intell_voice_engine_callback.h" + +namespace OHOS { +namespace IntellVoiceEngine { +using OnWakeupEventCb = std::function; + +class WakeupAdapterListener : public IntellVoiceAdapterListener { +public: + explicit WakeupAdapterListener(OnWakeupEventCb wakeupEventCb); + ~WakeupAdapterListener(); + + void SetCallback(const sptr &cb); + void OnIntellVoiceHdiEvent( + const OHOS::HDI::IntelligentVoice::Engine::V1_0::IntellVoiceEngineCallBackEvent &event) override; + +private: + void BackupCallBackEvent(const OHOS::HDI::IntelligentVoice::Engine::V1_0::IntellVoiceEngineCallBackEvent &event); + +private: + std::mutex mutex_; + std::shared_ptr historyEvent_ = nullptr; + sptr cb_ = nullptr; + OnWakeupEventCb wakeupEventCb_ = nullptr; +}; +} // namespace IntellVoice +} // namespace OHOS +#endif \ No newline at end of file diff --git a/services/intell_voice_engine/server/wakeup/wakeup_engine.cpp b/services/intell_voice_engine/server/wakeup/wakeup_engine.cpp new file mode 100755 index 0000000..c7e4437 --- /dev/null +++ b/services/intell_voice_engine/server/wakeup/wakeup_engine.cpp @@ -0,0 +1,337 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "wakeup_engine.h" +#include +#include "securec.h" +#include "intell_voice_log.h" + +#include "v1_0/iintell_voice_engine_manager.h" +#include "v1_0/iintell_voice_engine_callback.h" + +#include "time_util.h" +#include "scope_guard.h" +#include "adapter_callback_service.h" +#include "intell_voice_service_manager.h" +#include "ability_manager_client.h" +#include "memory_guard.h" + +using namespace OHOS::HDI::IntelligentVoice::Engine::V1_0; +using namespace OHOS::IntellVoiceUtils; +using namespace OHOS::AudioStandard; +#define LOG_TAG "WakeupEngine" + +namespace OHOS { +namespace IntellVoiceEngine { +static constexpr uint32_t MIN_BUFFER_SIZE = 1280; +static constexpr uint32_t INTERVAL = 50; +static const std::string RECOGNITION_FILE = "/data/data/recognition.pcm"; + +WakeupEngine::WakeupEngine() +{ + INTELL_VOICE_LOG_INFO("enter"); + + capturerOptions_.streamInfo.channels = AudioChannel::MONO; + capturerOptions_.streamInfo.samplingRate = AudioSamplingRate::SAMPLE_RATE_16000; + capturerOptions_.streamInfo.format = AudioSampleFormat::SAMPLE_S16LE; + capturerOptions_.capturerInfo.sourceType = SourceType::SOURCE_TYPE_MIC; + capturerOptions_.capturerInfo.capturerFlags = 0; +} + +WakeupEngine::~WakeupEngine() +{ + auto mgr = IIntellVoiceEngineManager::Get(); + if (mgr != nullptr) { + mgr->ReleaseAdapter(desc_); + } + adapter_ = nullptr; + callback_ = nullptr; +} + +void WakeupEngine::OnDetected() +{ + INTELL_VOICE_LOG_INFO("on detected"); + StartAbility(); + SetParameter("VprTrdType=0;WakeupScene=0"); + Start(true); +} + +void WakeupEngine::OnWakeupEvent(int32_t msgId, int32_t result) +{ + if (msgId == INTELL_VOICE_ENGINE_MSG_RECOGNIZE_COMPLETE) { + std::thread(&WakeupEngine::OnWakeupRecognition, this).detach(); + } +} + +void WakeupEngine::OnWakeupRecognition() +{ + INTELL_VOICE_LOG_INFO("on wakeup recognition"); + { + std::lock_guard lock(mutex_); + + if (fileSource_ != nullptr) { + fileSource_->Stop(); + fileSource_ = nullptr; + } + } + + const auto &manager = IntellVoiceServiceManager::GetInstance(); + if (manager != nullptr) { + manager->StartDetection(); + } + + Stop(); +} + +bool WakeupEngine::SetCallback() +{ + std::lock_guard lock(mutex_); + if (adapter_ == nullptr) { + INTELL_VOICE_LOG_ERROR("adapter is nullptr"); + return false; + } + + adapterListener_ = std::make_shared( + std::bind(&WakeupEngine::OnWakeupEvent, this, std::placeholders::_1, std::placeholders::_2)); + if (adapterListener_ == nullptr) { + INTELL_VOICE_LOG_ERROR("adapterListener_ is nullptr"); + return false; + } + + callback_ = sptr(new (std::nothrow) AdapterCallbackService(adapterListener_)); + if (callback_ == nullptr) { + INTELL_VOICE_LOG_ERROR("callback_ is nullptr"); + return false; + } + + adapter_->SetCallback(callback_); + return true; +} + +bool WakeupEngine::Init() +{ + desc_.adapterType = WAKEUP_ADAPTER_TYPE; + auto mgr = IIntellVoiceEngineManager::Get(); + if (mgr == nullptr) { + INTELL_VOICE_LOG_ERROR("failed to get engine manager"); + return false; + } + + mgr->CreateAdapter(desc_, adapter_); + if (adapter_ == nullptr) { + INTELL_VOICE_LOG_ERROR("adapter is nullptr"); + return false; + } + + if (!SetCallback()) { + INTELL_VOICE_LOG_ERROR("failed to set callback"); + return false; + } + + IntellVoiceEngineInfo info = { + .wakeupPhrase = "\xE5\xB0\x8F\xE8\x89\xBA\xE5\xB0\x8F\xE8\x89\xBA", + .isPcmFromExternal = false, + .minBufSize = 1280, + .sampleChannels = 1, + .bitsPerSample = 16, + .sampleRate = 16000, + }; + + if (Attach(info) != 0) { + INTELL_VOICE_LOG_ERROR("failed to attach"); + return false; + } + + return true; +} + +void WakeupEngine::SetCallback(sptr object) +{ + std::lock_guard lock(mutex_); + if (adapterListener_ == nullptr) { + INTELL_VOICE_LOG_ERROR("adapter listener is nullptr"); + return; + } + + sptr callback = iface_cast(object); + if (callback == nullptr) { + INTELL_VOICE_LOG_ERROR("callback is nullptr"); + return; + } + + adapterListener_->SetCallback(callback); +} + +int32_t WakeupEngine::Attach(const IntellVoiceEngineInfo &info) +{ + std::lock_guard lock(mutex_); + INTELL_VOICE_LOG_INFO("attach"); + if (adapter_ == nullptr) { + INTELL_VOICE_LOG_ERROR("adapter is nullptr"); + return -1; + } + + isPcmFromExternal_ = info.isPcmFromExternal; + + IntellVoiceEngineAdapterInfo adapterInfo = { + .wakeupPhrase = info.wakeupPhrase, + .minBufSize = info.minBufSize, + .sampleChannels = info.sampleChannels, + .bitsPerSample = info.bitsPerSample, + .sampleRate = info.sampleRate, + }; + return adapter_->Attach(adapterInfo); +} + +int32_t WakeupEngine::Detach(void) +{ + std::lock_guard lock(mutex_); + if (adapter_ == nullptr) { + INTELL_VOICE_LOG_ERROR("adapter is nullptr"); + return -1; + } + return adapter_->Detach(); +} + +int32_t WakeupEngine::Start(bool isLast) +{ + std::lock_guard lock(mutex_); + INTELL_VOICE_LOG_INFO("enter"); + if (adapter_ == nullptr) { + INTELL_VOICE_LOG_ERROR("adapter is nullptr"); + return -1; + } + + if (IntellVoiceServiceManager::GetInstance()->ApplyArbitration(INTELL_VOICE_WAKEUP, ENGINE_EVENT_START) != + ARBITRATION_OK) { + INTELL_VOICE_LOG_ERROR("policy manager reject to start engine"); + return 0; + } + + StartInfo info = { + .isLast = isLast, + }; + if (adapter_->Start(info)) { + INTELL_VOICE_LOG_ERROR("start adapter failed"); + return -1; + } + + if (isPcmFromExternal_) { + INTELL_VOICE_LOG_INFO("pcm is from external"); + return 0; + } + + if (!StartFileSource()) { + INTELL_VOICE_LOG_ERROR("start file source failed"); + adapter_->Stop(); + return -1; + } + + INTELL_VOICE_LOG_INFO("exit"); + return 0; +} + +void WakeupEngine::StartAbility() +{ + AAFwk::Want want; + const std::unique_ptr &historyInfoMgr = + IntellVoiceServiceManager::GetInstance()->GetHistoryInfoMgr(); + if (historyInfoMgr == nullptr) { + INTELL_VOICE_LOG_ERROR("historyInfoMgr is nullptr"); + return; + } + + std::string bundleName = historyInfoMgr->GetWakeupEngineBundleName(); + std::string abilityName = historyInfoMgr->GetWakeupEngineAbilityName(); + INTELL_VOICE_LOG_INFO("bundleName:%{public}s, abilityName:%{public}s", bundleName.c_str(), abilityName.c_str()); + want.SetElementName(bundleName, abilityName); + want.SetParam("serviceName", std::string("intell_voice")); + AAFwk::AbilityManagerClient::GetInstance()->StartAbility(want); +} + +int32_t WakeupEngine::SetParameter(const std::string &keyValueList) +{ + if (SetParameterInner(keyValueList)) { + INTELL_VOICE_LOG_INFO("inner parameter"); + return 0; + } + + return EngineBase::SetParameter(keyValueList); +} + +bool WakeupEngine::SetParameterInner(const std::string &keyValueList) +{ + std::lock_guard lock(mutex_); + + const auto &manager = IntellVoiceServiceManager::GetInstance(); + if (manager == nullptr) { + INTELL_VOICE_LOG_ERROR(); + return false; + } + + std::map kvpairs; + SplitStringToKVPair(keyValueList, kvpairs); + for (auto it : kvpairs) { + if (it.first == std::string("start_stream")) { + INTELL_VOICE_LOG_INFO("start stream:%{public}s", it.second.c_str()); + manager->StopDetection(); + return true; + } + if (it.first == std::string("stop_stream")) { + INTELL_VOICE_LOG_INFO("stop stream:%{public}s", it.second.c_str()); + manager->StartDetection(); + return true; + } + } + + return false; +} + +bool WakeupEngine::StartFileSource() +{ + auto listener = std::make_unique( + [&](uint8_t *buffer, uint32_t size) { + if (adapter_ != nullptr) { + std::vector audioBuff(&buffer[0], &buffer[size]); + adapter_->WriteAudio(audioBuff); + } + }, + [&](bool isError) + { + INTELL_VOICE_LOG_INFO("end of pcm, isError:%d", isError); + if (adapter_ != nullptr) { + adapter_->SetParameter("end_of_pcm=true"); + } + }); + if (listener == nullptr) { + INTELL_VOICE_LOG_ERROR("create listener failed"); + return false; + } + + fileSource_ = std::make_unique(MIN_BUFFER_SIZE, INTERVAL, RECOGNITION_FILE, std::move(listener)); + if (fileSource_ == nullptr) { + INTELL_VOICE_LOG_ERROR("create file source failed"); + return false; + } + + if (!fileSource_->Start()) { + INTELL_VOICE_LOG_ERROR("start capturer failed"); + fileSource_ = nullptr; + return false; + } + + return true; +} +} // namespace IntellVoice +} // namespace OHOS diff --git a/services/intell_voice_engine/server/wakeup/wakeup_engine.h b/services/intell_voice_engine/server/wakeup/wakeup_engine.h new file mode 100755 index 0000000..6973a55 --- /dev/null +++ b/services/intell_voice_engine/server/wakeup/wakeup_engine.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef WAKEUP_ENGINE_H +#define WAKEUP_ENGINE_H +#include +#include +#include "engine_base.h" +#include "intell_voice_engine_stub.h" +#include "wakeup_adapter_listener.h" +#include "v1_0/iintell_voice_engine_callback.h" + +#include "audio_info.h" +#include "file_source.h" +#include "intell_voice_generic_factory.h" + +namespace OHOS { +namespace IntellVoiceEngine { +class WakeupEngine : public EngineBase { +public: + ~WakeupEngine(); + bool Init() override; + void SetCallback(sptr object) override; + int32_t Attach(const IntellVoiceEngineInfo &info) override; + int32_t Detach(void) override; + int32_t Start(bool isLast) override; + int32_t SetParameter(const std::string &keyValueList) override; + + void OnDetected() override; + +private: + WakeupEngine(); + void OnWakeupEvent(int32_t msgId, int32_t result); + + void OnWakeupRecognition(); + bool SetCallback(); + bool StartFileSource(); + void StartAbility(); + bool SetParameterInner(const std::string &keyValueList); + +private: + bool isPcmFromExternal_ = false; + std::shared_ptr adapterListener_ = nullptr; + sptr callback_ = nullptr; + OHOS::AudioStandard::AudioCapturerOptions capturerOptions_; + std::unique_ptr fileSource_ = nullptr; + friend class IntellVoiceUtils::SptrFactory; +}; +} +} +#endif \ No newline at end of file diff --git a/services/intell_voice_trigger/server/connector_mgr/i_intell_voice_trigger_connector_callback.h b/services/intell_voice_trigger/server/connector_mgr/i_intell_voice_trigger_connector_callback.h new file mode 100755 index 0000000..a759b56 --- /dev/null +++ b/services/intell_voice_trigger/server/connector_mgr/i_intell_voice_trigger_connector_callback.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef I_INTELL_VOICE_TRIGGER_CONNECTOR_CALLBACK_H +#define I_INTELL_VOICE_TRIGGER_CONNECTOR_CALLBACK_H + +#include "v1_0/intell_voice_trigger_types.h" + +namespace OHOS { +namespace IntellVoiceTrigger { +using OHOS::HDI::IntelligentVoice::Trigger::V1_0::IntellVoiceRecognitionEvent; + +class IIntellVoiceTriggerConnectorCallback { +public: + IIntellVoiceTriggerConnectorCallback() = default; + virtual ~IIntellVoiceTriggerConnectorCallback() = default; + + virtual void OnRecognition(int32_t modelHandle, const struct IntellVoiceRecognitionEvent &event) = 0; +}; +} +} +#endif \ No newline at end of file diff --git a/services/intell_voice_trigger/server/connector_mgr/i_intell_voice_trigger_connector_internal.h b/services/intell_voice_trigger/server/connector_mgr/i_intell_voice_trigger_connector_internal.h new file mode 100755 index 0000000..9d64f7e --- /dev/null +++ b/services/intell_voice_trigger/server/connector_mgr/i_intell_voice_trigger_connector_internal.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef I_INTELL_VOICE_TRIGGER_CONNECTOR_INTERNAL_H +#define I_INTELL_VOICE_TRIGGER_CONNECTOR_INTERNAL_H + +#include +#include +#include "trigger_connector_common_type.h" +#include "i_intell_voice_trigger_connector_module.h" +#include "i_intell_voice_trigger_connector_callback.h" + +namespace OHOS { +namespace IntellVoiceTrigger { +class IIntellVoiceTriggerConnectorInternal { +public: + IIntellVoiceTriggerConnectorInternal() = default; + virtual ~IIntellVoiceTriggerConnectorInternal() = default; + + virtual std::vector ListModuleDescriptors() = 0; + virtual std::shared_ptr GetModule(const std::string &adapterName, + std::shared_ptr callback) = 0; +}; +} +} +#endif \ No newline at end of file diff --git a/services/intell_voice_trigger/server/connector_mgr/i_intell_voice_trigger_connector_module.h b/services/intell_voice_trigger/server/connector_mgr/i_intell_voice_trigger_connector_module.h new file mode 100755 index 0000000..3102b98 --- /dev/null +++ b/services/intell_voice_trigger/server/connector_mgr/i_intell_voice_trigger_connector_module.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef I_INTELL_VOICE_TRIGGER_CONNECTOR_MODULE_H +#define I_INTELL_VOICE_TRIGGER_CONNECTOR_MODULE_H + +#include +#include +#include "trigger_base_type.h" + +namespace OHOS { +namespace IntellVoiceTrigger { +class IIntellVoiceTriggerConnectorModule { +public: + IIntellVoiceTriggerConnectorModule() = default; + virtual ~IIntellVoiceTriggerConnectorModule() = default; + + virtual int32_t LoadModel(std::shared_ptr model, int32_t &modelHandle) = 0; + virtual int32_t UnloadModel(int32_t modelHandle) = 0; + virtual int32_t Start(int32_t modelHandle) = 0; + virtual int32_t Stop(int32_t modelHandle) = 0; +}; +} +} +#endif \ No newline at end of file diff --git a/services/intell_voice_trigger/server/connector_mgr/trigger_callback_impl.cpp b/services/intell_voice_trigger/server/connector_mgr/trigger_callback_impl.cpp new file mode 100755 index 0000000..4d69e91 --- /dev/null +++ b/services/intell_voice_trigger/server/connector_mgr/trigger_callback_impl.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "trigger_callback_impl.h" +#include "intell_voice_log.h" + +using namespace OHOS::HDI::IntelligentVoice::Trigger::V1_0; + +#define LOG_TAG "TriggerCallbackImpl" + +namespace OHOS { +namespace IntellVoiceTrigger { +TriggerCallbackImpl::TriggerCallbackImpl(std::shared_ptr listener) + :listener_(listener) +{ +} + +int32_t TriggerCallbackImpl::OnRecognitionHdiEvent(const IntellVoiceRecognitionEvent &event, int32_t cookie) +{ + if (listener_ == nullptr) { + INTELL_VOICE_LOG_ERROR("listener_ is nullptr"); + return -1; + } + + listener_->OnRecognitionHdiEvent(event, cookie); + return 0; +} +} +} \ No newline at end of file diff --git a/services/intell_voice_trigger/server/connector_mgr/trigger_callback_impl.h b/services/intell_voice_trigger/server/connector_mgr/trigger_callback_impl.h new file mode 100755 index 0000000..c704451 --- /dev/null +++ b/services/intell_voice_trigger/server/connector_mgr/trigger_callback_impl.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef INTELL_VOICE_TRIGGER_CALLBACK_IMPL_H +#define INTELL_VOICE_TRIGGER_CALLBACK_IMPL_H + +#include "v1_0/iintell_voice_trigger_callback.h" +#include "i_intell_voice_trigger_adapter_listener.h" + +namespace OHOS { +namespace IntellVoiceTrigger { +using OHOS::HDI::IntelligentVoice::Trigger::V1_0::IntellVoiceRecognitionEvent; +using OHOS::HDI::IntelligentVoice::Trigger::V1_0::IIntellVoiceTriggerCallback; + +class TriggerCallbackImpl final : public IIntellVoiceTriggerCallback { +public: + explicit TriggerCallbackImpl(std::shared_ptr listener); + virtual ~TriggerCallbackImpl() = default; + + int32_t OnRecognitionHdiEvent(const IntellVoiceRecognitionEvent &event, int32_t cookie) override; + +private: + std::shared_ptr listener_ = nullptr; +}; +} +} +#endif \ No newline at end of file diff --git a/services/intell_voice_trigger/server/connector_mgr/trigger_connector.cpp b/services/intell_voice_trigger/server/connector_mgr/trigger_connector.cpp new file mode 100755 index 0000000..b9cab13 --- /dev/null +++ b/services/intell_voice_trigger/server/connector_mgr/trigger_connector.cpp @@ -0,0 +1,392 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifdef TRIGGER_MANAGER_TEST +#include +#endif + +#include "trigger_connector_internal_impl.h" +#include "intell_voice_log.h" +#include "v1_0/iintell_voice_trigger_manager.h" +#include "scope_guard.h" +#include "trigger_callback_impl.h" +#include "memory_guard.h" + +#define LOG_TAG "TriggerConnector" + +using namespace std; +using namespace OHOS::IntellVoiceUtils; +using namespace OHOS::HDI::IntelligentVoice::Trigger::V1_0; + +namespace OHOS { +namespace IntellVoiceTrigger { +TriggerConnector::TriggerConnector(const IntellVoiceTriggerAdapterDsecriptor &desc) +{ + desc_.adapterName = desc.adapterName; + auto mgr = IIntellVoiceTriggerManager::Get(); + if (mgr != nullptr) { + mgr->LoadAdapter(desc_, adapter_); + if (adapter_ == nullptr) { + INTELL_VOICE_LOG_ERROR("failed to load adapter, adapterName is %{public}s", desc_.adapterName.c_str()); + } + } else { + INTELL_VOICE_LOG_INFO("can not get intell voice trigger manager"); + } +} + +TriggerConnector::~TriggerConnector() +{ + auto mgr = IIntellVoiceTriggerManager::Get(); + if (mgr != nullptr) { + mgr->UnloadAdapter(desc_); + } + adapter_ = nullptr; +} + +std::shared_ptr TriggerConnector::GetModule( + std::shared_ptr callback) +{ + if (adapter_ == nullptr) { + INTELL_VOICE_LOG_ERROR("adapter is nullptr"); + return nullptr; + } + + if (callback == nullptr) { + INTELL_VOICE_LOG_ERROR("callback is nullptr"); + return nullptr; + } + + std::shared_ptr session = std::make_shared(callback, adapter_); + if (session == nullptr) { + INTELL_VOICE_LOG_ERROR("failed to malloc session"); + return nullptr; + } + activeSessions_.insert(session); + return session; +} + +IntellVoiceTriggerProperties TriggerConnector::GetProperties() +{ + IntellVoiceTriggerProperties properties; + return properties; +} + +void TriggerConnector::OnReceive(const ServiceStatus &status) +{ + OHOS::IntellVoiceUtils::MemoryGuard memoryGuard; + INTELL_VOICE_LOG_INFO("enter"); + if (status.serviceName != INTELL_VOICE_TRIGGER_SERVICE) { + return; + } + if (adapter_ != nullptr) { + return; + } + auto mgr = IIntellVoiceTriggerManager::Get(); + if (mgr != nullptr) { + mgr->LoadAdapter(desc_, adapter_); + if (adapter_ == nullptr) { + INTELL_VOICE_LOG_ERROR("failed to load adapter, adapterName is %{public}s", desc_.adapterName.c_str()); + } + } else { + INTELL_VOICE_LOG_ERROR("failed to get trigger manager"); + } +} + +TriggerConnector::TriggerSession::TriggerSession( + std::shared_ptr callback, const sptr &adapter) + : callback_(callback), adapter_(adapter) +{ + BaseThread::Start(); +} + +TriggerConnector::TriggerSession::~TriggerSession() +{ + Message msg(MSG_TYPE_QUIT); + SendMsg(msg); + Join(); +} + +int32_t TriggerConnector::TriggerSession::LoadModel( + std::shared_ptr model, int32_t &modelHandle) +{ + std::lock_guard lock(mutex_); + std::shared_ptr loadedModle = Model::Create(this); + if (loadedModle == nullptr) { + INTELL_VOICE_LOG_ERROR("failed to malloc intell voice model"); + return -1; + } + + int32_t result = loadedModle->Load(model, modelHandle); + if (result != 0) { + INTELL_VOICE_LOG_ERROR("failed to load generic trigger model"); + return result; + } + loadedModels_.insert(std::make_pair(modelHandle, loadedModle)); + return result; +} + +int32_t TriggerConnector::TriggerSession::UnloadModel(int32_t modelHandle) +{ + std::lock_guard lock(mutex_); + auto it = loadedModels_.find(modelHandle); + if ((it == loadedModels_.end()) || (it->second == nullptr)) { + INTELL_VOICE_LOG_ERROR("failed to find model"); + return -1; + } + return it->second->Unload(); +} + +int32_t TriggerConnector::TriggerSession::Start(int32_t modelHandle) +{ + std::lock_guard lock(mutex_); + auto it = loadedModels_.find(modelHandle); + if ((it == loadedModels_.end()) || (it->second == nullptr)) { + INTELL_VOICE_LOG_ERROR("failed to find model"); + return -1; + } + return it->second->Start(); +} + +int32_t TriggerConnector::TriggerSession::Stop(int32_t modelHandle) +{ + std::lock_guard lock(mutex_); + auto it = loadedModels_.find(modelHandle); + if ((it == loadedModels_.end()) || (it->second == nullptr)) { + INTELL_VOICE_LOG_ERROR("failed to find model"); + return -1; + } + return it->second->Stop(); +} + +void TriggerConnector::TriggerSession::HandleRecognitionHdiEvent(std::shared_ptr event, + int32_t modelHandle) +{ + Message msg(MSG_TYPE_RECOGNITION_HDI_EVENT); + + msg.obj2 = static_pointer_cast(event); + msg.arg1 = modelHandle; + SendMsg(msg); +} + +void TriggerConnector::TriggerSession::ProcessRecognitionHdiEvent(const Message &message) +{ + int32_t modelHandle = message.arg1; + std::shared_ptr event = + static_pointer_cast(message.obj2); + if (event == nullptr) { + INTELL_VOICE_LOG_ERROR("event is nullptr"); + return; + } + + { + std::lock_guard lock(mutex_); + auto it = loadedModels_.find(modelHandle); + if ((it != loadedModels_.end()) && (it->second != nullptr)) { + INTELL_VOICE_LOG_INFO("receive recognition event"); + } + } + callback_->OnRecognition(modelHandle, *(event.get())); +} + +bool TriggerConnector::TriggerSession::HandleMsg(Message &message) +{ + bool quit = false; + + switch (message.mWhat) { + case MSG_TYPE_RECOGNITION_HDI_EVENT: + ProcessRecognitionHdiEvent(message); + break; + default: + INTELL_VOICE_LOG_WARN("invalid msg id: %{public}d", message.mWhat); + break; + } + + if (message.mWhat == MSG_TYPE_QUIT) { + quit = true; + } + + return quit; +} + +std::shared_ptr TriggerConnector::TriggerSession::Model::Create( + TriggerSession *session) +{ + return std::shared_ptr(new (std::nothrow) Model(session)); +} + +int32_t TriggerConnector::TriggerSession::Model::Load( + std::shared_ptr model, int32_t &modelHandle) +{ + INTELL_VOICE_LOG_INFO("enter"); + if (GetState() != IDLE) { + INTELL_VOICE_LOG_ERROR("model has already loaded"); + return -1; + } + + callback_ = sptr(new (std::nothrow) TriggerCallbackImpl(shared_from_this())); + if (callback_ == nullptr) { + INTELL_VOICE_LOG_ERROR("callback_ is nullptr"); + return -1; + } + + IntellVoiceTriggerModel triggerModel; + triggerModel.data = CreateAshmemFromModelData(model->GetData()); + if (triggerModel.data == nullptr) { + INTELL_VOICE_LOG_ERROR("data is nullptr"); + return -1; + } + triggerModel.type = static_cast(model->GetType()); + triggerModel.uid = static_cast(model->GetUuid()); + + ON_SCOPE_EXIT { + INTELL_VOICE_LOG_INFO("close ashmem"); + triggerModel.data->UnmapAshmem(); + triggerModel.data->CloseAshmem(); + }; + + int32_t handle; + int32_t ret = session_->GetAdapter()->LoadModel(triggerModel, callback_, 0, handle); + if (ret != 0) { + INTELL_VOICE_LOG_ERROR("failed to load model"); + return ret; + } + (void)model; + handle_ = handle; + modelHandle = handle_; + SetState(LOADED); + return ret; +} + +int32_t TriggerConnector::TriggerSession::Model::Start() +{ + INTELL_VOICE_LOG_INFO("enter"); + if (GetState() != LOADED) { + INTELL_VOICE_LOG_ERROR("model has not loaded"); + return -1; + } + + int32_t ret = session_->GetAdapter()->Start(handle_); + if (ret != 0) { + INTELL_VOICE_LOG_ERROR("failed to load model"); + return ret; + } + +#ifdef TRIGGER_MANAGER_TEST + std::thread(&TriggerConnector::TriggerSession::Model::TriggerManagerCallbackTest, this).detach(); +#endif + + SetState(ACTIVE); + return ret; +} + +int32_t TriggerConnector::TriggerSession::Model::Stop() +{ + INTELL_VOICE_LOG_INFO("enter"); + if (GetState() != ACTIVE) { + INTELL_VOICE_LOG_ERROR("model has not activated"); + return -1; + } + + int32_t ret = session_->GetAdapter()->Stop(handle_); + if (ret != 0) { + INTELL_VOICE_LOG_ERROR("failed to load model"); + return ret; + } + + SetState(LOADED); + return ret; +} + +int32_t TriggerConnector::TriggerSession::Model::Unload() +{ + INTELL_VOICE_LOG_INFO("enter"); + if (GetState() == IDLE) { + INTELL_VOICE_LOG_ERROR("model has not loaded"); + return -1; + } + + int32_t ret = session_->GetAdapter()->UnloadModel(handle_); + if (ret != 0) { + INTELL_VOICE_LOG_ERROR("failed to load model"); + return ret; + } + + SetState(IDLE); + return ret; +} + +#ifdef TRIGGER_MANAGER_TEST +void TriggerConnector::TriggerSession::Model::TriggerManagerCallbackTest() +{ + INTELL_VOICE_LOG_ERROR("enter"); + IntellVoiceRecognitionEvent recognitionEvent; + recognitionEvent.status = static_cast(0); + recognitionEvent.type = static_cast(1); + recognitionEvent.modelHandle = handle_; + TriggerConnector::TriggerSession::Model::OnRecognitionHdiEvent(recognitionEvent, 0); +} +#endif + +void TriggerConnector::TriggerSession::Model::OnRecognitionHdiEvent(const IntellVoiceRecognitionEvent& event, + int32_t cookie) +{ + (void)cookie; + std::shared_ptr recognitionEvent = std::make_shared(); + if (recognitionEvent == nullptr) { + INTELL_VOICE_LOG_ERROR("recognitionEvent is nullptr"); + return; + } + + recognitionEvent->status = event.status; + recognitionEvent->type = event.type; + recognitionEvent->modelHandle = event.modelHandle; + + INTELL_VOICE_LOG_INFO("handle: %{public}d", handle_); + session_->HandleRecognitionHdiEvent(recognitionEvent, handle_); +} + +sptr TriggerConnector::TriggerSession::Model::CreateAshmemFromModelData( + const std::vector &modelData) +{ + if (modelData.size() == 0) { + INTELL_VOICE_LOG_ERROR("data is empty"); + return nullptr; + } + + sptr buffer = OHOS::Ashmem::CreateAshmem("ModelData", modelData.size()); + if (buffer == nullptr) { + INTELL_VOICE_LOG_ERROR("failed to create ashmem"); + return nullptr; + } + + if (!buffer->MapReadAndWriteAshmem()) { + INTELL_VOICE_LOG_ERROR("failed to map ashmem"); + goto ERR_EXIT; + } + + if (!buffer->WriteToAshmem(modelData.data(), modelData.size(), 0)) { + INTELL_VOICE_LOG_ERROR("failed to write ashmem"); + goto ERR_EXIT; + } + + INTELL_VOICE_LOG_INFO("model data size:%{public}zu", modelData.size()); + return buffer; + +ERR_EXIT: + buffer->UnmapAshmem(); + buffer->CloseAshmem(); + return nullptr; +} +} // namespace IntellVoiceTrigger +} // namespace OHOS \ No newline at end of file diff --git a/services/intell_voice_trigger/server/connector_mgr/trigger_connector.h b/services/intell_voice_trigger/server/connector_mgr/trigger_connector.h new file mode 100755 index 0000000..fedc824 --- /dev/null +++ b/services/intell_voice_trigger/server/connector_mgr/trigger_connector.h @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef INTELL_VOICE_TRIGGER_CONNECTOR_H +#define INTELL_VOICE_TRIGGER_CONNECTOR_H + +#include +#include +#include +#include +#include +#include +#include "v1_0/iintell_voice_trigger_adapter.h" +#include "i_intell_voice_trigger_adapter_listener.h" +#include "i_intell_voice_trigger_connector_module.h" +#include "i_intell_voice_trigger_connector_callback.h" +#include "msg_handle_thread.h" + +namespace OHOS { +namespace IntellVoiceTrigger { +using OHOS::HDI::ServiceManager::V1_0::ServiceStatus; +using OHOS::HDI::ServiceManager::V1_0::ServStatListenerStub; + +using OHOS::HDI::IntelligentVoice::Trigger::V1_0::IntellVoiceTriggerAdapterDsecriptor; +using OHOS::HDI::IntelligentVoice::Trigger::V1_0::IntellVoiceTriggerProperties; +using OHOS::HDI::IntelligentVoice::Trigger::V1_0::IIntellVoiceTriggerAdapter; +using OHOS::HDI::IntelligentVoice::Trigger::V1_0::IntellVoiceRecognitionEvent; +using OHOS::HDI::IntelligentVoice::Trigger::V1_0::IIntellVoiceTriggerCallback; + +const std::string INTELL_VOICE_TRIGGER_SERVICE = "intell_voice_trigger_manager_service"; + +class TriggerConnector : public ServStatListenerStub { +public: + explicit TriggerConnector(const IntellVoiceTriggerAdapterDsecriptor &desc); + ~TriggerConnector() override; + std::shared_ptr GetModule( + std::shared_ptr callback); + IntellVoiceTriggerProperties GetProperties(); + void OnReceive(const ServiceStatus &status) override; + +private: + class TriggerSession : public IIntellVoiceTriggerConnectorModule, public OHOS::IntellVoiceUtils::MsgHandleThread { + public: + TriggerSession(std::shared_ptr callback, + const sptr &adapter); + ~TriggerSession() override; + const sptr &GetAdapter() + { + return adapter_; + } + std::shared_ptr GetCallback() + { + return callback_; + } + int32_t LoadModel(std::shared_ptr model, int32_t &modelHandle) override; + int32_t UnloadModel(int32_t modelHandle) override; + int32_t Start(int32_t modelHandle) override; + int32_t Stop(int32_t modelHandle) override; + + void HandleRecognitionHdiEvent(std::shared_ptr event, + int32_t modelHandle); + private: + enum MsgType { + MSG_TYPE_NONE, + MSG_TYPE_RECOGNITION_HDI_EVENT, + MSG_TYPE_QUIT, + }; + + private: + class Model : public IIntellVoiceTriggerAdapterListener, public std::enable_shared_from_this { + public: + static std::shared_ptr Create(TriggerSession *session); + int32_t Load(std::shared_ptr model, int32_t &modelHandle); + int32_t Unload(); + int32_t Start(); + int32_t Stop(); +#ifdef TRIGGER_MANAGER_TEST + void TriggerManagerCallbackTest(); +#endif + public: + void OnRecognitionHdiEvent(const IntellVoiceRecognitionEvent &event, int32_t cookie) override; + + enum ModelState { + IDLE, + LOADED, + ACTIVE, + }; + ModelState GetState() + { + return state_.load(); + } + + void SetState(ModelState state) + { + state_.store(state); + } + + private: + explicit Model(TriggerSession *session) : session_(session) {} + sptr CreateAshmemFromModelData(const std::vector &modelData); + int32_t handle_ = 0; + std::atomic state_ = IDLE; + TriggerSession *session_ = nullptr; + sptr callback_ = nullptr; + }; // Model + + private: + bool HandleMsg(OHOS::IntellVoiceUtils::Message &message) override; + void ProcessRecognitionHdiEvent(const OHOS::IntellVoiceUtils::Message &message); + private: + std::mutex mutex_ {}; + std::shared_ptr callback_ = nullptr; + const OHOS::sptr &adapter_; + std::map> loadedModels_; + }; // TriggerSession + +private: + IntellVoiceTriggerAdapterDsecriptor desc_; + sptr adapter_ = nullptr; + std::set> activeSessions_; +}; +} // namespace IntellVoiceTrigger +} // namespace OHOS +#endif \ No newline at end of file diff --git a/services/intell_voice_trigger/server/connector_mgr/trigger_connector_common_type.h b/services/intell_voice_trigger/server/connector_mgr/trigger_connector_common_type.h new file mode 100755 index 0000000..8a4b8c6 --- /dev/null +++ b/services/intell_voice_trigger/server/connector_mgr/trigger_connector_common_type.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef INTELL_VOICE_TRIGGER_CONNECTOR_COMMON_TYPE_H +#define INTELL_VOICE_TRIGGER_CONNECTOR_COMMON_TYPE_H + +#include +#include "v1_0/intell_voice_trigger_types.h" + +namespace OHOS { +namespace IntellVoiceTrigger { +using OHOS::HDI::IntelligentVoice::Trigger::V1_0::IntellVoiceTriggerProperties; + +struct TriggerConnectorModuleDesc { + std::string adapterName; + IntellVoiceTriggerProperties properties; +}; +} +} +#endif \ No newline at end of file diff --git a/services/intell_voice_trigger/server/connector_mgr/trigger_connector_internal_impl.cpp b/services/intell_voice_trigger/server/connector_mgr/trigger_connector_internal_impl.cpp new file mode 100755 index 0000000..4c31bee --- /dev/null +++ b/services/intell_voice_trigger/server/connector_mgr/trigger_connector_internal_impl.cpp @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "trigger_connector_internal_impl.h" +#include +#include +#include "intell_voice_log.h" +#include "v1_0/iintell_voice_trigger_manager.h" +#include "memory_guard.h" + +#define LOG_TAG "TriggerConnectorInternalImpl" + +using namespace OHOS::HDI::IntelligentVoice::Trigger::V1_0; + +namespace OHOS { +namespace IntellVoiceTrigger { +TriggerConnectorInternalImpl::TriggerConnectorInternalImpl() +{ + OHOS::IntellVoiceUtils::MemoryGuard memoryGuard; + IntellVoiceTriggerAdapterDsecriptor descriptor; + descriptor.adapterName = "primary"; + + sptr servmgr_ = IServiceManager::Get(); + if (servmgr_ != nullptr) { + auto connector = sptr(new (std::nothrow) TriggerConnector(descriptor)); + if (connector != nullptr) { + servmgr_->RegisterServiceStatusListener(connector, DEVICE_CLASS_DEFAULT); + connectors_[descriptor.adapterName] = connector; + } else { + INTELL_VOICE_LOG_ERROR("failed to malloc connector"); + } + } else { + INTELL_VOICE_LOG_ERROR("failed to get hdf service manager"); + } +} + +TriggerConnectorInternalImpl::~TriggerConnectorInternalImpl() +{ + INTELL_VOICE_LOG_DEBUG("TriggerConnectorInternalImpl destructor"); + for (auto it = connectors_.begin(); it != connectors_.end(); ++it) { + servmgr_->UnregisterServiceStatusListener(it->second); + } +} + +std::vector TriggerConnectorInternalImpl::ListModuleDescriptors() +{ + std::vector ret; + for (auto it = connectors_.begin(); it != connectors_.end(); ++it) { + TriggerConnectorModuleDesc item; + item.adapterName = it->first; + item.properties = it->second->GetProperties(); + ret.emplace_back(item); + } + return ret; +} + +std::shared_ptr TriggerConnectorInternalImpl::GetModule( + const std::string &adapterName, std::shared_ptr callback) +{ + auto it = connectors_.find(adapterName); + if ((it == connectors_.end()) || (it->second == nullptr)) { + INTELL_VOICE_LOG_ERROR("failed to find connector"); + return nullptr; + } + + return it->second->GetModule(callback); +} +} +} diff --git a/services/intell_voice_trigger/server/connector_mgr/trigger_connector_internal_impl.h b/services/intell_voice_trigger/server/connector_mgr/trigger_connector_internal_impl.h new file mode 100755 index 0000000..b63a391 --- /dev/null +++ b/services/intell_voice_trigger/server/connector_mgr/trigger_connector_internal_impl.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef INTELL_VOICE_TRIGGER_CONNECTOR_INTERNAL_IMPL_H +#define INTELL_VOICE_TRIGGER_CONNECTOR_INTERNAL_IMPL_H + +#include +#include +#include "i_intell_voice_trigger_connector_internal.h" +#include "trigger_connector.h" + +using OHOS::HDI::ServiceManager::V1_0::IServiceManager; + +namespace OHOS { +namespace IntellVoiceTrigger { +class TriggerConnectorInternalImpl : public IIntellVoiceTriggerConnectorInternal { +public: + TriggerConnectorInternalImpl(); + ~TriggerConnectorInternalImpl() override; + std::vector ListModuleDescriptors() override; + std::shared_ptr GetModule(const std::string &adapterName, + std::shared_ptr callback) override; + +private: + std::map> connectors_; + sptr servmgr_ = nullptr; +}; +} +} +#endif \ No newline at end of file diff --git a/services/intell_voice_trigger/server/connector_mgr/trigger_connector_internal_validation.cpp b/services/intell_voice_trigger/server/connector_mgr/trigger_connector_internal_validation.cpp new file mode 100755 index 0000000..80baa53 --- /dev/null +++ b/services/intell_voice_trigger/server/connector_mgr/trigger_connector_internal_validation.cpp @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "trigger_connector_internal_validation.h" +#include "intell_voice_log.h" + +#define LOG_TAG "TriggerConnectorInternalValidation" + +namespace OHOS { +namespace IntellVoiceTrigger { +TriggerConnectorInternalValidation::TriggerConnectorInternalValidation( + std::unique_ptr delegate) : delegate_(std::move(delegate)) +{ +} + +std::vector TriggerConnectorInternalValidation::ListModuleDescriptors() +{ + std::lock_guard lock(mutex_); + std::vector ret = delegate_->ListModuleDescriptors(); + if (ret.empty()) { + INTELL_VOICE_LOG_ERROR("no trigger connector module desc"); + return ret; + } + + if (moduleDescs_.empty()) { + for (auto it : ret) { + moduleDescs_.insert(it.adapterName); + } + } else { + if (ret.size() != moduleDescs_.size()) { + INTELL_VOICE_LOG_ERROR("size different, ret size:%zu, module descs size:%zu", ret.size(), + moduleDescs_.size()); + return {}; + } + + for (auto it : ret) { + if (moduleDescs_.count(it.adapterName) == 0) { + INTELL_VOICE_LOG_ERROR("adapter name:%s does not exist", it.adapterName.c_str()); + return {}; + } + } + } + return ret; +} + +std::shared_ptr TriggerConnectorInternalValidation::GetModule( + const std::string &adapterName, std::shared_ptr callback) +{ + std::lock_guard lock(mutex_); + if (moduleDescs_.count(adapterName) == 0) { + INTELL_VOICE_LOG_ERROR("adapter name:%s does not exist", adapterName.c_str()); + return nullptr; + } + std::shared_ptr moduleValidation = + std::make_shared(callback); + if (moduleValidation == nullptr) { + INTELL_VOICE_LOG_ERROR("failed to malloc connector module validation"); + return nullptr; + } + + auto delegate = delegate_->GetModule(adapterName, moduleValidation->GetCallbackWrapper()); + if (delegate == nullptr) { + INTELL_VOICE_LOG_ERROR("failed to get delegate"); + return nullptr; + } + moduleValidation->SetDelegate(delegate); + return moduleValidation; +} + +bool TriggerConnectorInternalValidation::TriggerConnectorModuleValidation::ValidationUtils::ValidateGenericModel( + std::shared_ptr model) +{ + if (model == nullptr) { + INTELL_VOICE_LOG_ERROR("generic model is nullptr"); + return false; + } + + if (model->GetType() != TriggerModel::TriggerModelType::GENERIC_TYPE) { + INTELL_VOICE_LOG_ERROR("generic model type:%d is invalid", model->GetType()); + return false; + } + + if (model->GetData().size() == 0) { + INTELL_VOICE_LOG_ERROR("generic model data size is zero"); + return false; + } + + return true; +} + +TriggerConnectorInternalValidation::TriggerConnectorModuleValidation::TriggerConnectorModuleValidation( + std::shared_ptr callback) +{ + callbackWrapper_ = std::make_shared(callback); + if (callbackWrapper_ == nullptr) { + INTELL_VOICE_LOG_ERROR("failed to malloc callback wrapper"); + } +} + +int32_t TriggerConnectorInternalValidation::TriggerConnectorModuleValidation::LoadModel( + std::shared_ptr model, int32_t &modelHandle) +{ + if (!ValidationUtils::ValidateGenericModel(model)) { + INTELL_VOICE_LOG_ERROR(); + return -1; + } + return delegate_->LoadModel(model, modelHandle); +} + +int32_t TriggerConnectorInternalValidation::TriggerConnectorModuleValidation::UnloadModel( + int32_t modelHandle) +{ + return delegate_->UnloadModel(modelHandle); +} + +int32_t TriggerConnectorInternalValidation::TriggerConnectorModuleValidation::Start(int32_t modelHandle) +{ + return delegate_->Start(modelHandle); +} + +int32_t TriggerConnectorInternalValidation::TriggerConnectorModuleValidation::Stop(int32_t modelHandle) +{ + return delegate_->Stop(modelHandle); +} +} +} diff --git a/services/intell_voice_trigger/server/connector_mgr/trigger_connector_internal_validation.h b/services/intell_voice_trigger/server/connector_mgr/trigger_connector_internal_validation.h new file mode 100755 index 0000000..e1dd0eb --- /dev/null +++ b/services/intell_voice_trigger/server/connector_mgr/trigger_connector_internal_validation.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef INTELL_VOICE_TRIGGER_CONNECTOR_INTERNAL_VALIDATION_H +#define INTELL_VOICE_TRIGGER_CONNECTOR_INTERNAL_VALIDATION_H + +#include +#include +#include +#include "v1_0/intell_voice_trigger_types.h" +#include "i_intell_voice_trigger_connector_internal.h" + +namespace OHOS { +namespace IntellVoiceTrigger { +using OHOS::HDI::IntelligentVoice::Trigger::V1_0::IntellVoiceRecognitionEvent; + +class TriggerConnectorInternalValidation : public IIntellVoiceTriggerConnectorInternal { +public: + explicit TriggerConnectorInternalValidation(std::unique_ptr delegate); + std::vector ListModuleDescriptors() override; + std::shared_ptr GetModule(const std::string &adapterName, + std::shared_ptr callback) override; + +private: + std::mutex mutex_; + std::set moduleDescs_; + std::unique_ptr delegate_ = nullptr; + +private: + class TriggerConnectorModuleValidation : public IIntellVoiceTriggerConnectorModule { + public: + explicit TriggerConnectorModuleValidation(std::shared_ptr callback); + std::shared_ptr GetCallbackWrapper() + { + return callbackWrapper_; + } + void SetDelegate(std::shared_ptr delegate) + { + delegate_ = delegate; + } + int32_t LoadModel(std::shared_ptr model, int32_t &modelHandle) override; + int32_t UnloadModel(int32_t modelHandle) override; + int32_t Start(int32_t modelHandle) override; + int32_t Stop(int32_t modelHandle) override; + + private: + class TriggerConnectorCallbackValidation : public IIntellVoiceTriggerConnectorCallback { + public: + explicit TriggerConnectorCallbackValidation(std::shared_ptr delegate) + : delegate_(delegate) {} + void OnRecognition(int32_t modelHandle, const IntellVoiceRecognitionEvent &event) override + { + delegate_->OnRecognition(modelHandle, event); + } + private: + std::shared_ptr delegate_; + }; + + class ValidationUtils { + public: + static bool ValidateGenericModel(std::shared_ptr model); + }; + private: + std::shared_ptr delegate_ = nullptr; + std::shared_ptr callbackWrapper_ = nullptr; + }; +}; +} +} +#endif diff --git a/services/intell_voice_trigger/server/connector_mgr/trigger_connector_mgr.cpp b/services/intell_voice_trigger/server/connector_mgr/trigger_connector_mgr.cpp new file mode 100755 index 0000000..8ea4479 --- /dev/null +++ b/services/intell_voice_trigger/server/connector_mgr/trigger_connector_mgr.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "trigger_connector_mgr.h" +#include "intell_voice_log.h" +#include "trigger_connector_internal_validation.h" +#include "trigger_connector_internal_impl.h" + +#define LOG_TAG "TriggerConnectorMgr" + +namespace OHOS { +namespace IntellVoiceTrigger { +std::unique_ptr TriggerConnectorMgr::g_connectorMgr = + std::unique_ptr( + new (std::nothrow) TriggerConnectorMgr(std::make_unique( + std::make_unique()))); + +TriggerConnectorMgr::TriggerConnectorMgr(std::unique_ptr delegate) + : delegate_(std::move(delegate)) +{} + +std::unique_ptr &TriggerConnectorMgr::GetInstance() +{ + return g_connectorMgr; +} + +std::vector TriggerConnectorMgr::ListConnectorModuleDescriptors() +{ + if (delegate_ == nullptr) { + INTELL_VOICE_LOG_ERROR("delegate_ is nullptr"); + return {}; + } + + return delegate_->ListModuleDescriptors(); +} + +std::shared_ptr TriggerConnectorMgr::GetConnectorModule( + const std::string &adapterName, std::shared_ptr callback) +{ + if (delegate_ == nullptr) { + INTELL_VOICE_LOG_ERROR("delegate_ is nullptr"); + return nullptr; + } + + return delegate_->GetModule(adapterName, callback); +} +} // namespace IntellVoiceTrigger +} // namespace OHOS \ No newline at end of file diff --git a/services/intell_voice_trigger/server/connector_mgr/trigger_connector_mgr.h b/services/intell_voice_trigger/server/connector_mgr/trigger_connector_mgr.h new file mode 100755 index 0000000..dad2153 --- /dev/null +++ b/services/intell_voice_trigger/server/connector_mgr/trigger_connector_mgr.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef INTELL_VOICE_TRIGGER_CONNECTOR_MGR_H +#define INTELL_VOICE_TRIGGER_CONNECTOR_MGR_H + +#include "nocopyable.h" +#include "i_intell_voice_trigger_connector_internal.h" + +namespace OHOS { +namespace IntellVoiceTrigger { +class TriggerConnectorMgr { +public: + ~TriggerConnectorMgr() = default; + static std::unique_ptr &GetInstance(); + std::vector ListConnectorModuleDescriptors(); + std::shared_ptr GetConnectorModule( + const std::string &adapterName, std::shared_ptr callback); + +private: + explicit TriggerConnectorMgr(std::unique_ptr delegate); + +private: + static std::unique_ptr g_connectorMgr; + std::unique_ptr delegate_ = nullptr; + + DISALLOW_COPY(TriggerConnectorMgr); + DISALLOW_MOVE(TriggerConnectorMgr); +}; +} // namespace IntellVoiceTrigger +} // namespace OHOS +#endif \ No newline at end of file diff --git a/services/intell_voice_trigger/server/i_intell_voice_trigger_adapter_listener.h b/services/intell_voice_trigger/server/i_intell_voice_trigger_adapter_listener.h new file mode 100755 index 0000000..ea712f7 --- /dev/null +++ b/services/intell_voice_trigger/server/i_intell_voice_trigger_adapter_listener.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef I_INTELL_VOICE_TRIGGER_ADAPTER_LISTENER_H +#define I_INTELL_VOICE_TRIGGER_ADAPTER_LISTENER_H +#include "v1_0/intell_voice_trigger_types.h" + +namespace OHOS { +namespace IntellVoiceTrigger { +using OHOS::HDI::IntelligentVoice::Trigger::V1_0::IntellVoiceRecognitionEvent; + +class IIntellVoiceTriggerAdapterListener { +public: + virtual ~IIntellVoiceTriggerAdapterListener() = default; + virtual void OnRecognitionHdiEvent(const IntellVoiceRecognitionEvent &event, int32_t cookie) = 0; +}; +} +} +#endif diff --git a/services/intell_voice_trigger/server/i_intell_voice_trigger_detector_callback.h b/services/intell_voice_trigger/server/i_intell_voice_trigger_detector_callback.h new file mode 100755 index 0000000..7ecdee1 --- /dev/null +++ b/services/intell_voice_trigger/server/i_intell_voice_trigger_detector_callback.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef I_INTELL_VOICE_TRIGGER_DETECTOR_CALLBACK_H +#define I_INTELL_VOICE_TRIGGER_DETECTOR_CALLBACK_H + +#include +#include +#include + +namespace OHOS { +namespace IntellVoiceTrigger { +struct DetectorEvent { + DetectorEvent(int32_t audioFormat, std::vector data) : audioFormat_(audioFormat) + { + data_.swap(data); + } + int32_t audioFormat_ {0}; + std::vector data_; +}; + +class IIntellVoiceTriggerDetectorCallback { +public: + IIntellVoiceTriggerDetectorCallback() = default; + virtual ~IIntellVoiceTriggerDetectorCallback() {}; + + virtual void OnDetected(const std::shared_ptr &event) = 0; +}; +} // namespace IntellVoiceTrigger +} // namespace OHOS +#endif \ No newline at end of file diff --git a/services/intell_voice_trigger/server/i_intell_voice_trigger_recognition_callback.h b/services/intell_voice_trigger/server/i_intell_voice_trigger_recognition_callback.h new file mode 100755 index 0000000..ab42864 --- /dev/null +++ b/services/intell_voice_trigger/server/i_intell_voice_trigger_recognition_callback.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef I_INTELL_VOICE_TRIGGER_RECOGNITION_CALLBACK_H +#define I_INTELL_VOICE_TRIGGER_RECOGNITION_CALLBACK_H + +#include +#include +#include + +namespace OHOS { +namespace IntellVoiceTrigger { +struct GenericTriggerEvent { + int32_t modelHandle_ {0}; + int32_t audioFormat_ {0}; + std::vector data_; +}; + +class IIntellVoiceTriggerRecognitionCallback { +public: + IIntellVoiceTriggerRecognitionCallback() = default; + virtual ~IIntellVoiceTriggerRecognitionCallback() {}; + virtual void OnGenericTriggerDetected(const std::shared_ptr event) = 0; +}; +} // namespace IntellVoiceTrigger +} // namespace OHOS +#endif \ No newline at end of file diff --git a/services/intell_voice_trigger/server/trigger_base_type.cpp b/services/intell_voice_trigger/server/trigger_base_type.cpp new file mode 100755 index 0000000..ba19130 --- /dev/null +++ b/services/intell_voice_trigger/server/trigger_base_type.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "trigger_base_type.h" +#include "securec.h" +#include "intell_voice_log.h" + +#define LOG_TAG "TriggerBaseType" + +namespace OHOS { +namespace IntellVoiceTrigger { +TriggerModel::TriggerModel(TriggerModelType type, int32_t uuid, int32_t version) + : type_(type), uuid_(uuid), version_(version) +{} + +TriggerModel::~TriggerModel() +{ +} + +bool TriggerModel::SetData(const uint8_t *data, uint32_t size) +{ + if (size <= 0) { + INTELL_VOICE_LOG_ERROR("size is invalid"); + return false; + } + data_.resize(size); + + if (memcpy_s(data_.data(), data_.size(), data, size) != 0) { + INTELL_VOICE_LOG_ERROR("memcpy_s error"); + return false; + } + return true; +} + +bool TriggerModel::SetData(std::vectordata) +{ + if (data.size() <= 0) { + INTELL_VOICE_LOG_ERROR("size is invalid"); + return false; + } + data_.swap(data); + return true; +} + +void TriggerModel::Print() +{ + INTELL_VOICE_LOG_INFO("trigger model type:%{public}d", type_); + INTELL_VOICE_LOG_INFO("trigger model uuid:%{public}d", uuid_); + INTELL_VOICE_LOG_INFO("trigger model vendor uuid:%{public}d", vendorUuid_); + INTELL_VOICE_LOG_INFO("trigger model version:%{public}d", version_); + INTELL_VOICE_LOG_INFO("trigger model data size:%{public}lu", data_.size()); +} +} // namespace IntellVoiceTrigger +} // namespace OHOS \ No newline at end of file diff --git a/services/intell_voice_trigger/server/trigger_base_type.h b/services/intell_voice_trigger/server/trigger_base_type.h new file mode 100755 index 0000000..f2f01d2 --- /dev/null +++ b/services/intell_voice_trigger/server/trigger_base_type.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef INTELL_VOICE_TRIGGER_MODEL_H +#define INTELL_VOICE_TRIGGER_MODEL_H + +#include +#include +#include + +namespace OHOS { +namespace IntellVoiceTrigger { +class TriggerModel { +public: + enum TriggerModelType { + GENERIC_TYPE = 1, + UNKNOWN_TYPE = -1, + }; + + TriggerModel(TriggerModelType type, int32_t uuid, int32_t version); + virtual ~TriggerModel(); + + bool SetData(const uint8_t *data, uint32_t size); + bool SetData(std::vector data); + void Print(); + + int32_t GetUuid() + { + return uuid_; + } + + int32_t GetType() + { + return type_; + } + + int32_t GetVendorUuid() + { + return vendorUuid_; + } + + int32_t GetVersion() + { + return version_; + } + + std::vector GetData() + { + return data_; + } + +protected: + TriggerModelType type_ = UNKNOWN_TYPE; + int32_t uuid_ = -1; + int32_t vendorUuid_ = -1; + int32_t version_ = -1; + +private: + std::vector data_; +}; + +class GenericTriggerModel : public TriggerModel { +public: + GenericTriggerModel(int32_t uuid, int32_t version) + : TriggerModel(TriggerModel::TriggerModelType::GENERIC_TYPE, uuid, version) + {} + ~GenericTriggerModel() override + {} +}; +} // namespace IntellVoiceTrigger +} // namespace OHOS + +#endif \ No newline at end of file diff --git a/services/intell_voice_trigger/server/trigger_db_helper.cpp b/services/intell_voice_trigger/server/trigger_db_helper.cpp new file mode 100755 index 0000000..8f4c928 --- /dev/null +++ b/services/intell_voice_trigger/server/trigger_db_helper.cpp @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "trigger_db_helper.h" + +#include + +#include "intell_voice_log.h" +#include "rdb_errno.h" +#include "rdb_helper.h" +#include "rdb_open_callback.h" + +#define LOG_TAG "TriggerDbhelper" + +using namespace OHOS::NativeRdb; + +namespace OHOS { +namespace IntellVoiceTrigger { +class TriggerModelOpenCallback : public RdbOpenCallback { +public: + int OnCreate(RdbStore &rdbStore) override; + int OnUpgrade(RdbStore &rdbStore, int oldVersion, int newVersion) override; +}; + +int TriggerModelOpenCallback::OnCreate(RdbStore &store) +{ + INTELL_VOICE_LOG_DEBUG("OnCreate"); + std::string CREATE_TABLE_Trigger = + std::string("CREATE TABLE IF NOT EXISTS trigger ") + + std::string("(model_uuid INTEGER PRIMARY KEY, vendor_uuid INTEGER, data BLOB, model_version INTEGER)"); + + return store.ExecuteSql(CREATE_TABLE_Trigger); +} + +int TriggerModelOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) +{ + return E_OK; +} + +TriggerDbHelper::TriggerDbHelper() +{ + int errCode = E_OK; + RdbStoreConfig config("/data/service/el1/public/database/intell_voice_service_manager/triggerModel.db"); + TriggerModelOpenCallback helper; + store_ = RdbHelper::GetRdbStore(config, 1, helper, errCode); + if (store_ == nullptr) { + INTELL_VOICE_LOG_ERROR("store is nullptr"); + } +} + +TriggerDbHelper::~TriggerDbHelper() +{ + store_ = nullptr; +} + +bool TriggerDbHelper::UpdateGenericTriggerModel(std::shared_ptr model) +{ + std::lock_guard lock(mutex_); + INTELL_VOICE_LOG_INFO("db Update"); + + if (store_ == nullptr) { + INTELL_VOICE_LOG_ERROR("store is nullptr"); + return false; + } + + if (model == nullptr) { + INTELL_VOICE_LOG_ERROR("model is nullptr"); + return false; + } + + int64_t rowId = -1; + ValuesBucket values; + values.PutInt("model_uuid", model->GetUuid()); + values.PutInt("vendor_uuid", model->GetVendorUuid()); + values.PutBlob("data", model->GetData()); + values.PutInt("model_version", model->GetVersion()); + int ret = store_->InsertWithConflictResolution(rowId, "trigger", values, ConflictResolution::ON_CONFLICT_REPLACE); + if (ret != E_OK) { + INTELL_VOICE_LOG_ERROR("update generic model failed"); + return false; + } + return true; +} + +bool TriggerDbHelper::GetVendorUuid(std::unique_ptr &set, int32_t &vendorUuid) +{ + int columnIndex; + int ret = set->GetColumnIndex("vendor_uuid", columnIndex); + if (ret != E_OK) { + INTELL_VOICE_LOG_ERROR("failed to get model uuid column index"); + return false; + } + + ret = set->GetInt(columnIndex, vendorUuid); + if (ret != E_OK) { + INTELL_VOICE_LOG_ERROR("failed to get model uuid"); + return false; + } + return true; +} + +bool TriggerDbHelper::GetBlob(std::unique_ptr &set, std::vector &data) +{ + int columnIndex; + int ret = set->GetColumnIndex("data", columnIndex); + if (ret != E_OK) { + INTELL_VOICE_LOG_ERROR("failed to get data column index"); + return false; + } + + ret = set->GetBlob(columnIndex, data); + if (ret != E_OK) { + INTELL_VOICE_LOG_ERROR("failed to get data"); + return false; + } + return true; +} + +bool TriggerDbHelper::GetModelVersion(std::unique_ptr &set, int32_t &version) +{ + int columnIndex; + int ret = set->GetColumnIndex("model_version", columnIndex); + if (ret != E_OK) { + INTELL_VOICE_LOG_ERROR("failed to get model uuid column index"); + return false; + } + + ret = set->GetInt(columnIndex, version); + if (ret != E_OK) { + INTELL_VOICE_LOG_ERROR("failed to get model uuid"); + return false; + } + return true; +} + +std::shared_ptr TriggerDbHelper::GetGenericTriggerModel(const int32_t modelUuid) +{ + std::lock_guard lock(mutex_); + INTELL_VOICE_LOG_INFO("db get generic model"); + if (store_ == nullptr) { + INTELL_VOICE_LOG_ERROR("store is nullptr"); + return nullptr; + } + + std::unique_ptr set = store_->QuerySql( + "SELECT * FROM trigger WHERE model_uuid = ?", std::vector {std::to_string(modelUuid)}); + if (set == nullptr) { + INTELL_VOICE_LOG_ERROR("set is nullptr"); + return nullptr; + } + + set->GoToFirstRow(); + + int32_t vendorUuid; + if (!GetVendorUuid(set, vendorUuid)) { + INTELL_VOICE_LOG_ERROR("failed to get vendor uuid"); + return nullptr; + } + + std::vector data; + if (!GetBlob(set, data)) { + INTELL_VOICE_LOG_ERROR("failed to get data"); + return nullptr; + } + + int32_t modelVersion; + if (!GetModelVersion(set, modelVersion)) { + INTELL_VOICE_LOG_ERROR("failed to get model version"); + return nullptr; + } + + std::shared_ptr model = std::make_shared(modelUuid, modelVersion); + if (model == nullptr) { + INTELL_VOICE_LOG_ERROR("failed to alloc model"); + return nullptr; + } + model->SetData(data); + return model; +} + +void TriggerDbHelper::DeleteGenericTriggerModel(const int32_t modelUuid) +{ + std::lock_guard lock(mutex_); + INTELL_VOICE_LOG_INFO("db Delete"); + if (store_ == nullptr) { + INTELL_VOICE_LOG_ERROR("store is nullptr"); + return; + } + int deletedRows; + store_->Delete(deletedRows, "trigger", "model_uuid = ?", std::vector {std::to_string(modelUuid)}); +} +} // namespace IntellVoiceTrigger +} // namespace OHOS diff --git a/services/intell_voice_trigger/server/trigger_db_helper.h b/services/intell_voice_trigger/server/trigger_db_helper.h new file mode 100755 index 0000000..0f650fd --- /dev/null +++ b/services/intell_voice_trigger/server/trigger_db_helper.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef INTELL_VOICE_TRIGGER_DB_HELPER_H +#define INTELL_VOICE_TRIGGER_DB_HELPER_H +#include +#include + +#include "rdb_errno.h" +#include "rdb_helper.h" +#include "rdb_open_callback.h" +#include "trigger_base_type.h" + +namespace OHOS { +namespace IntellVoiceTrigger { +class TriggerDbHelper { +public: + TriggerDbHelper(); + ~TriggerDbHelper(); + bool UpdateGenericTriggerModel(std::shared_ptr model); + std::shared_ptr GetGenericTriggerModel(const int32_t modelUuid); + void DeleteGenericTriggerModel(const int32_t modelUuid); + +private: + bool GetVendorUuid(std::unique_ptr &set, int32_t &vendorUuid); + bool GetBlob(std::unique_ptr &set, std::vector &data); + bool GetModelVersion(std::unique_ptr &set, int32_t &version); + +private: + std::mutex mutex_; + std::shared_ptr store_ = nullptr; +}; +} +} +#endif diff --git a/services/intell_voice_trigger/server/trigger_detector.cpp b/services/intell_voice_trigger/server/trigger_detector.cpp new file mode 100755 index 0000000..4eac97d --- /dev/null +++ b/services/intell_voice_trigger/server/trigger_detector.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "trigger_detector.h" +#include "intell_voice_log.h" +#include "trigger_detector_recognition_callback.h" +#include "memory_guard.h" + +#define LOG_TAG "TriggerDetector" + +namespace OHOS { +namespace IntellVoiceTrigger { +TriggerDetector::TriggerDetector(int32_t uuid, std::shared_ptr service, + std::shared_ptr callback) : uuid_(uuid), service_(service) +{ + callback_ = std::make_shared(callback); + if (callback_ == nullptr) { + INTELL_VOICE_LOG_ERROR("callback_ is nullptr"); + } +} + +TriggerDetector::~TriggerDetector() +{ + service_ = nullptr; +} + +bool TriggerDetector::StartRecognition() +{ + OHOS::IntellVoiceUtils::MemoryGuard memoryGuard; + if (service_ == nullptr) { + INTELL_VOICE_LOG_ERROR("service_ is nullptr"); + return false; + } + service_->StartRecognition(uuid_, callback_); + return true; +} + +bool TriggerDetector::StopRecognition() +{ + OHOS::IntellVoiceUtils::MemoryGuard memoryGuard; + if (service_ == nullptr) { + INTELL_VOICE_LOG_ERROR("service_ is nullptr"); + return false; + } + service_->StopRecognition(uuid_, callback_); + return true; +} +} +} \ No newline at end of file diff --git a/services/intell_voice_trigger/server/trigger_detector.h b/services/intell_voice_trigger/server/trigger_detector.h new file mode 100755 index 0000000..91c560e --- /dev/null +++ b/services/intell_voice_trigger/server/trigger_detector.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef INTELL_VOICE_TRIGGER_DETECTOR_H +#define INTELL_VOICE_TRIGGER_DETECTOR_H + +#include +#include "trigger_service.h" +#include "i_intell_voice_trigger_detector_callback.h" +#include "i_intell_voice_trigger_recognition_callback.h" + +namespace OHOS { +namespace IntellVoiceTrigger { +class TriggerDetector { +public: + TriggerDetector(int32_t uuid, std::shared_ptr service, + std::shared_ptr callback); + ~TriggerDetector(); + bool StartRecognition(); + bool StopRecognition(); + +private: + + int32_t uuid_ = -1; + std::shared_ptr service_ = nullptr; + std::shared_ptr callback_ = nullptr; +}; +} +} +#endif \ No newline at end of file diff --git a/services/intell_voice_trigger/server/trigger_detector_callback.cpp b/services/intell_voice_trigger/server/trigger_detector_callback.cpp new file mode 100755 index 0000000..d6c7006 --- /dev/null +++ b/services/intell_voice_trigger/server/trigger_detector_callback.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "trigger_detector_callback.h" +#include "intell_voice_log.h" +#include "wakeup_engine.h" + +using namespace OHOS::IntellVoiceEngine; +#define LOG_TAG "TriggerDetectorCallback" + +namespace OHOS { +namespace IntellVoiceTrigger { +TriggerDetectorCallback::TriggerDetectorCallback(OnDetectedCb cb) : cb_(cb) +{} + +void TriggerDetectorCallback::OnDetected(const std::shared_ptr &event) +{ + if (event == nullptr) { + INTELL_VOICE_LOG_ERROR("event is nullptr"); + return; + } + + if (event->data_.size() > 0) { + INTELL_VOICE_LOG_INFO( + "receive DetectorEvent dataSize_: %{public}zu, data_[0]: %{public}d", event->data_.size(), event->data_[0]); + } + cb_(); +} +} // namespace IntellVoiceTrigger +} // namespace OHOS \ No newline at end of file diff --git a/services/intell_voice_trigger/server/trigger_detector_callback.h b/services/intell_voice_trigger/server/trigger_detector_callback.h new file mode 100755 index 0000000..e7ce6d6 --- /dev/null +++ b/services/intell_voice_trigger/server/trigger_detector_callback.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef INTELL_VOICE_TRIGGER_DETECTOR_CALLBACK_H +#define INTELL_VOICE_TRIGGER_DETECTOR_CALLBACK_H + +#include +#include "i_intell_voice_trigger_detector_callback.h" + +namespace OHOS { +namespace IntellVoiceTrigger { +using OnDetectedCb = std::function; + +class TriggerDetectorCallback : public IIntellVoiceTriggerDetectorCallback { +public: + explicit TriggerDetectorCallback(OnDetectedCb cb); + void OnDetected(const std::shared_ptr &event) override; + +private: + OnDetectedCb cb_; +}; +} +} +#endif \ No newline at end of file diff --git a/services/intell_voice_trigger/server/trigger_detector_recognition_callback.cpp b/services/intell_voice_trigger/server/trigger_detector_recognition_callback.cpp new file mode 100755 index 0000000..c5b948e --- /dev/null +++ b/services/intell_voice_trigger/server/trigger_detector_recognition_callback.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "trigger_detector_recognition_callback.h" +#include "intell_voice_log.h" + +#define LOG_TAG "TriggerDetectorRecogCallback" + +namespace OHOS { +namespace IntellVoiceTrigger { +TriggerDetectorRecognitionCallback::TriggerDetectorRecognitionCallback( + std::shared_ptr callback) : callback_(callback) +{ +} + +void TriggerDetectorRecognitionCallback::OnGenericTriggerDetected( + const std::shared_ptr event) +{ + if (event == nullptr || callback_ == nullptr) { + INTELL_VOICE_LOG_ERROR("event or callback_ is nullptr"); + return; + } + + std::shared_ptr eventPayLoad = std::make_shared( + event->audioFormat_, event->data_); + + if (eventPayLoad == nullptr) { + INTELL_VOICE_LOG_ERROR("event or callback_ is nullptr"); + return; + } + + callback_->OnDetected(eventPayLoad); +} +} +} \ No newline at end of file diff --git a/services/intell_voice_trigger/server/trigger_detector_recognition_callback.h b/services/intell_voice_trigger/server/trigger_detector_recognition_callback.h new file mode 100755 index 0000000..4ef6767 --- /dev/null +++ b/services/intell_voice_trigger/server/trigger_detector_recognition_callback.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef INTELL_VOICE_TRIGGER_DETECTOR_RECOGNITION_CALLBACK_H +#define INTELL_VOICE_TRIGGER_DETECTOR_RECOGNITION_CALLBACK_H + +#include +#include +#include "i_intell_voice_trigger_recognition_callback.h" +#include "i_intell_voice_trigger_detector_callback.h" + +namespace OHOS { +namespace IntellVoiceTrigger { +class TriggerDetectorRecognitionCallback : public IIntellVoiceTriggerRecognitionCallback { +public: + explicit TriggerDetectorRecognitionCallback(std::shared_ptr callback); + ~TriggerDetectorRecognitionCallback() override {}; + void OnGenericTriggerDetected(const std::shared_ptr event) override; + +private: + + std::shared_ptr callback_ = nullptr; +}; +} +} +#endif \ No newline at end of file diff --git a/services/intell_voice_trigger/server/trigger_helper.cpp b/services/intell_voice_trigger/server/trigger_helper.cpp new file mode 100755 index 0000000..fa7b070 --- /dev/null +++ b/services/intell_voice_trigger/server/trigger_helper.cpp @@ -0,0 +1,314 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "trigger_helper.h" +#include "intell_voice_log.h" + +#include "trigger_connector_mgr.h" + +using namespace OHOS::HDI::IntelligentVoice::Trigger::V1_0; +using namespace std; +#define LOG_TAG "TriggerHelper" + +namespace OHOS { +namespace IntellVoiceTrigger { +TriggerModelData::TriggerModelData(int32_t uuid) +{ + uuid_ = uuid; +} + +TriggerModelData::~TriggerModelData() +{ +} + +void TriggerModelData::SetCallback(std::shared_ptr callback) +{ + if (callback == nullptr) { + INTELL_VOICE_LOG_ERROR("callback is nullptr"); + return; + } + callback_ = callback; +} + +std::shared_ptr TriggerModelData::GetCallback() +{ + return callback_; +} + +void TriggerModelData::SetModel(std::shared_ptr model) +{ + if (SameModel(model)) { + INTELL_VOICE_LOG_INFO("same model not need to update"); + return; + } + model_ = model; + model_->Print(); +} + +shared_ptr TriggerModelData::GetModel() +{ + return model_; +} + +bool TriggerModelData::SameModel(std::shared_ptr model) +{ + if (model == nullptr || model_ == nullptr) { + return false; + } + return model_->GetData() == model->GetData(); +} + +void TriggerModelData::SetState(ModelState state) +{ + state_ = state; +} + +ModelState TriggerModelData::GetState() +{ + return state_; +} + +void TriggerModelData::SetModelHandle(int32_t handle) +{ + modelHandle_ = handle; +} + +int32_t TriggerModelData::GetModelHandle() +{ + return modelHandle_; +} + +void TriggerModelData::Clear() +{ + callback_ = nullptr; +} + +TriggerHelper::TriggerHelper() +{ + moduleDesc_ = TriggerConnectorMgr::GetInstance()->ListConnectorModuleDescriptors(); +} + +TriggerHelper::~TriggerHelper() +{ + modelDataMap_.clear(); +} + +std::shared_ptr TriggerHelper::Create() +{ + return std::shared_ptr(new (std::nothrow) TriggerHelper()); +} + +int32_t TriggerHelper::StartGenericRecognition(int32_t uuid, std::shared_ptr model, + shared_ptr callback) +{ + INTELL_VOICE_LOG_INFO("enter"); + lock_guard lock(mutex_); + + auto modelData = GetTriggerModelData(uuid); + if (modelData == nullptr) { + INTELL_VOICE_LOG_ERROR("failed to get trigger model data"); + return -1; + } + + GetModule(); + + bool unload = !modelData->SameModel(model); + int32_t ret = InitRecognition(modelData, unload); + if (ret != 0) { + INTELL_VOICE_LOG_ERROR("failed to initialize recognition"); + return -1; + } + + modelData->SetModel(model); + modelData->SetCallback(callback); + + LoadModel(modelData); + return StartRecognition(modelData); +} + +int32_t TriggerHelper::StopGenericRecognition( + int32_t uuid, shared_ptr callback) +{ + INTELL_VOICE_LOG_INFO("enter"); + lock_guard lock(mutex_); + auto modelData = GetTriggerModelData(uuid); + if (modelData == nullptr) { + INTELL_VOICE_LOG_ERROR("failed to get trigger model data"); + return -1; + } + modelData->SetCallback(callback); + return StopRecognition(modelData); +} + +void TriggerHelper::GetModule() +{ + if (module_ != nullptr) { + return; + } + if (moduleDesc_.size() == 0) { + INTELL_VOICE_LOG_INFO("moduleDesc_ is empty"); + return; + } + module_ = + TriggerConnectorMgr::GetInstance()->GetConnectorModule(moduleDesc_[0].adapterName, shared_from_this()); + if (module_ == nullptr) { + INTELL_VOICE_LOG_ERROR("failed to get connector module"); + } +} + +int32_t TriggerHelper::InitRecognition(std::shared_ptr modelData, bool unload) +{ + INTELL_VOICE_LOG_INFO("enter"); + if (modelData->GetState() == MODEL_NOTLOADED) { + return 0; + } + int32_t ret = StopRecognition(modelData); + if (unload) { + ret = UnloadModel(modelData); + } + modelData->Clear(); + return ret; +} + +int32_t TriggerHelper::StartRecognition(shared_ptr modelData) +{ + if (modelData == nullptr) { + INTELL_VOICE_LOG_ERROR("modelData is nullptr"); + return -1; + } + if (modelData->GetState() != MODEL_LOADED) { + return 0; + } + INTELL_VOICE_LOG_INFO("enter"); + if (module_ == nullptr) { + INTELL_VOICE_LOG_ERROR("module_ is nullptr"); + return -1; + } + auto ret = module_->Start(modelData->GetModelHandle()); + modelData->SetState(MODEL_STARTED); + return ret; +} + +int32_t TriggerHelper::StopRecognition(shared_ptr modelData) +{ + if (modelData == nullptr) { + INTELL_VOICE_LOG_ERROR("modelData is nullptr"); + return -1; + } + if (modelData->GetState() != MODEL_STARTED) { + return 0; + } + INTELL_VOICE_LOG_INFO("enter"); + if (module_ == nullptr) { + INTELL_VOICE_LOG_ERROR("module_ is nullptr"); + return -1; + } + auto ret = module_->Stop(modelData->GetModelHandle()); + modelData->SetState(MODEL_LOADED); + return ret; +} + +int32_t TriggerHelper::LoadModel(shared_ptr modelData) +{ + INTELL_VOICE_LOG_INFO("enter"); + if (modelData == nullptr) { + INTELL_VOICE_LOG_ERROR("modelData is nullptr"); + return -1; + } + if (modelData->GetState() != MODEL_NOTLOADED) { + INTELL_VOICE_LOG_WARN("model is already loaded"); + return 0; + } + + if (module_ == nullptr) { + INTELL_VOICE_LOG_ERROR("module_ is nullptr"); + return -1; + } + + int32_t handle; + auto ret = module_->LoadModel(modelData->GetModel(), handle); + modelData->SetModelHandle(handle); + modelData->SetState(MODEL_LOADED); + INTELL_VOICE_LOG_INFO("exit, handle: %d", handle); + return ret; +} + +int32_t TriggerHelper::UnloadModel(shared_ptr modelData) +{ + if (modelData == nullptr) { + INTELL_VOICE_LOG_ERROR("modelData is nullptr"); + return -1; + } + if (modelData->GetState() != MODEL_LOADED) { + return 0; + } + INTELL_VOICE_LOG_INFO("enter"); + if (module_ == nullptr) { + INTELL_VOICE_LOG_ERROR("module_ is nullptr"); + return -1; + } + auto ret = module_->UnloadModel(modelData->GetModelHandle()); + modelData->SetState(MODEL_NOTLOADED); + return ret; +} + +shared_ptr TriggerHelper::GetTriggerModelData(int32_t uuid) +{ + INTELL_VOICE_LOG_INFO("enter, uuid is :%d", uuid); + auto it = modelDataMap_.find(uuid); + if (it != modelDataMap_.end() && it->second != nullptr) { + return it->second; + } + + auto modelData = std::make_shared(uuid); + if (modelData == nullptr) { + INTELL_VOICE_LOG_INFO("modelData is nullptr"); + return nullptr; + } + modelDataMap_.insert(std::make_pair(uuid, modelData)); + return modelData; +} + +void TriggerHelper::OnRecognition(int32_t modelHandle, const IntellVoiceRecognitionEvent &event) +{ + INTELL_VOICE_LOG_INFO("enter, modelHandle:%{public}d", modelHandle); + lock_guard lock(mutex_); + std::shared_ptr callback = nullptr; + for (auto iter : modelDataMap_) { + if (iter.second == nullptr) { + INTELL_VOICE_LOG_ERROR("uuid: %d, model data is nullptr", iter.first); + continue; + } + + if (iter.second->GetModelHandle() == modelHandle) { + callback = iter.second->GetCallback(); + break; + } + } + + if (callback == nullptr) { + INTELL_VOICE_LOG_ERROR("trigger recognition callback is nullptr, modelHandle: %{public}d", modelHandle); + return; + } + + auto genericEvent = std::make_shared(); + if (genericEvent == nullptr) { + INTELL_VOICE_LOG_ERROR("genericEvent is nullptr"); + return; + } + genericEvent->modelHandle_ = modelHandle; + callback->OnGenericTriggerDetected(genericEvent); +} +} // namespace IntellVoiceTrigger +} // namespace OHOS \ No newline at end of file diff --git a/services/intell_voice_trigger/server/trigger_helper.h b/services/intell_voice_trigger/server/trigger_helper.h new file mode 100755 index 0000000..6c90d4c --- /dev/null +++ b/services/intell_voice_trigger/server/trigger_helper.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef INTELL_VOICE_TRIGGER_HELPER_H +#define INTELL_VOICE_TRIGGER_HELPER_H + +#include +#include +#include "msg_handle_thread.h" +#include "trigger_base_type.h" +#include "i_intell_voice_trigger_recognition_callback.h" + +#include "i_intell_voice_trigger_connector_module.h" +#include "i_intell_voice_trigger_connector_callback.h" +#include "trigger_connector_common_type.h" + +namespace OHOS { +namespace IntellVoiceTrigger { +enum ModelState { MODEL_NOTLOADED, MODEL_LOADED, MODEL_STARTED, MODEL_STATE_BUT }; + +class TriggerModelData { +public: + explicit TriggerModelData(int32_t uuid); + ~TriggerModelData(); + void SetCallback(std::shared_ptr callback); + std::shared_ptr GetCallback(); + void SetModel(std::shared_ptr model); + std::shared_ptr GetModel(); + void SetState(ModelState state); + ModelState GetState(); + void SetModelHandle(int32_t handle); + int32_t GetModelHandle(); + + bool SameModel(std::shared_ptr model); + void Clear(); + +public: + int32_t uuid_ = -1; + +private: + ModelState state_ = MODEL_NOTLOADED; + std::shared_ptr model_ = nullptr; + std::shared_ptr callback_ = nullptr; + int32_t modelHandle_ = 0; +}; + +class TriggerHelper : public IIntellVoiceTriggerConnectorCallback, + public std::enable_shared_from_this { +public: + ~TriggerHelper(); + + static std::shared_ptr Create(); + + int32_t StartGenericRecognition(int32_t uuid, std::shared_ptr model, + std::shared_ptr callback); + int32_t StopGenericRecognition(int32_t uuid, std::shared_ptr callback); + + std::shared_ptr GetTriggerModelData(int32_t uuid); + +private: + TriggerHelper(); + void GetModule(); + int32_t InitRecognition(std::shared_ptr modelData, bool unload); + int32_t StartRecognition(std::shared_ptr modelData); + int32_t StopRecognition(std::shared_ptr modelData); + int32_t LoadModel(std::shared_ptr modelData); + int32_t UnloadModel(std::shared_ptr modelData); + + void OnRecognition(int32_t modelHandle, const IntellVoiceRecognitionEvent &event) override; + +private: + std::mutex mutex_; + + std::map> modelDataMap_; + std::shared_ptr module_ = nullptr; + std::vector moduleDesc_; +}; +} // namespace IntellVoiceTrigger +} // namespace OHOS +#endif \ No newline at end of file diff --git a/services/intell_voice_trigger/server/trigger_manager.cpp b/services/intell_voice_trigger/server/trigger_manager.cpp new file mode 100755 index 0000000..b390d47 --- /dev/null +++ b/services/intell_voice_trigger/server/trigger_manager.cpp @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "trigger_manager.h" +#include "trigger_service.h" +#include "intell_voice_log.h" +#include "memory_guard.h" + +#define LOG_TAG "TriggerManager" + +namespace OHOS { +namespace IntellVoiceTrigger { +std::mutex TriggerManager::instanceMutex_; +std::shared_ptr TriggerManager::instance_ = nullptr; + +TriggerManager::TriggerManager() +{ + OHOS::IntellVoiceUtils::MemoryGuard memoryGuard; + service_ = std::make_shared(); + if (service_ == nullptr) { + INTELL_VOICE_LOG_ERROR("service_ is nullptr"); + } +} + +TriggerManager::~TriggerManager() +{ + service_ = nullptr; +} + +std::shared_ptr TriggerManager::GetInstance() +{ + if (instance_ == nullptr) { + std::lock_guard autoLock(instanceMutex_); + if (instance_ == nullptr) { + instance_ = std::shared_ptr(new TriggerManager()); + } + } + return instance_; +} + +void TriggerManager::UpdateModel(std::shared_ptr model) +{ + if (service_ == nullptr) { + INTELL_VOICE_LOG_ERROR("service_ is nullptr"); + } + service_->UpdateGenericTriggerModel(model); +} + +void TriggerManager::DeleteModel(int32_t uuid) +{ + if (service_ == nullptr) { + INTELL_VOICE_LOG_ERROR("service_ is nullptr"); + } + service_->DeleteGenericTriggerModel(uuid); +} + +std::shared_ptr TriggerManager::GetModel(int32_t uuid) +{ + if (service_ == nullptr) { + INTELL_VOICE_LOG_ERROR("service_ is nullptr"); + return nullptr; + } + return service_->GetGenericTriggerModel(uuid); +} + +std::shared_ptr TriggerManager::CreateTriggerDetector( + int32_t uuid, std::shared_ptr callback) +{ + OHOS::IntellVoiceUtils::MemoryGuard memoryGuard; + std::shared_ptr detector = std::make_shared(uuid, service_, callback); + if (detector == nullptr) { + INTELL_VOICE_LOG_ERROR("detector is nullptr"); + return nullptr; + } + + detectors_[uuid] = detector; + return detector; +} + +void TriggerManager::ReleaseTriggerDetector(int32_t uuid) +{ + OHOS::IntellVoiceUtils::MemoryGuard memoryGuard; + auto it = detectors_.find(uuid); + if (it == detectors_.end()) { + return; + } + + detectors_.erase(it); +} +} // namespace IntellVoiceTrigger +} // namespace OHOS \ No newline at end of file diff --git a/services/intell_voice_trigger/server/trigger_manager.h b/services/intell_voice_trigger/server/trigger_manager.h new file mode 100755 index 0000000..e0b4ed5 --- /dev/null +++ b/services/intell_voice_trigger/server/trigger_manager.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef INTELL_VOICE_TRIGGER_MANAGER_H +#define INTELL_VOICE_TRIGGER_MANAGER_H + +#include +#include +#include "trigger_base_type.h" +#include "trigger_service.h" +#include "trigger_detector.h" +#include "i_intell_voice_trigger_detector_callback.h" + +namespace OHOS { +namespace IntellVoiceTrigger { +class TriggerManager { +public: + ~TriggerManager(); + static std::shared_ptr GetInstance(); + + void UpdateModel(std::shared_ptr model); + void DeleteModel(int32_t uuid); + std::shared_ptr GetModel(int32_t uuid); + std::shared_ptr CreateTriggerDetector( + int32_t uuid, std::shared_ptr callback); + void ReleaseTriggerDetector(int32_t uuid); + +private: + explicit TriggerManager(); + +private: + std::map> detectors_; + std::shared_ptr service_; + + static std::mutex instanceMutex_; + static std::shared_ptr instance_; +}; +} // namespace IntellVoiceTrigger +} // namespace OHOS +#endif \ No newline at end of file diff --git a/services/intell_voice_trigger/server/trigger_service.cpp b/services/intell_voice_trigger/server/trigger_service.cpp new file mode 100755 index 0000000..41f920a --- /dev/null +++ b/services/intell_voice_trigger/server/trigger_service.cpp @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "trigger_service.h" + +#include + +#include "intell_voice_log.h" + +#define LOG_TAG "TriggerService" +using namespace std; + +namespace OHOS { +namespace IntellVoiceTrigger { +TriggerService::TriggerService() +{ + dbHelper_ = std::make_shared(); + if (dbHelper_ == nullptr) { + INTELL_VOICE_LOG_ERROR("dbHelper_ is nullptr"); + } + + triggerHelper_ = TriggerHelper::Create(); + if (triggerHelper_ == nullptr) { + INTELL_VOICE_LOG_ERROR("triggerHelper_ is nullptr"); + } +} + +TriggerService::~TriggerService() +{} + +void TriggerService::UpdateGenericTriggerModel(std::shared_ptr model) +{ + INTELL_VOICE_LOG_INFO("enter"); + if (dbHelper_ == nullptr) { + INTELL_VOICE_LOG_ERROR("dbHelper_ is nullptr"); + return; + } + + if (model == nullptr) { + INTELL_VOICE_LOG_ERROR("trigger model is null"); + return; + } + + if (!dbHelper_->UpdateGenericTriggerModel(model)) { + INTELL_VOICE_LOG_ERROR("failed to update generic model"); + } +} + +void TriggerService::DeleteGenericTriggerModel(int32_t uuid) +{ + INTELL_VOICE_LOG_INFO("enter"); + if (dbHelper_ == nullptr) { + INTELL_VOICE_LOG_ERROR("dbHelper_ is nullptr"); + return; + } + dbHelper_->DeleteGenericTriggerModel(uuid); +} + +std::shared_ptr TriggerService::GetGenericTriggerModel(int32_t uuid) +{ + INTELL_VOICE_LOG_INFO("enter"); + + if (dbHelper_ == nullptr) { + INTELL_VOICE_LOG_ERROR("dbHelper_ is nullptr"); + return nullptr; + } + + auto model = dbHelper_->GetGenericTriggerModel(uuid); + if (model == nullptr) { + INTELL_VOICE_LOG_ERROR("failed to get generic trigger model"); + return nullptr; + } + + return model; +} + +int32_t TriggerService::StartRecognition( + int32_t uuid, std::shared_ptr callback) +{ + if (triggerHelper_ == nullptr) { + INTELL_VOICE_LOG_ERROR("trigger helper is nullptr"); + return -1; + } + + auto model = GetGenericTriggerModel(uuid); + if (model == nullptr) { + INTELL_VOICE_LOG_ERROR("trigger model is nullptr, uuid:%{public}d", uuid); + return -1; + } + + return triggerHelper_->StartGenericRecognition(uuid, model, callback); +} + +int32_t TriggerService::StopRecognition(int32_t uuid, std::shared_ptr callback) +{ + if (triggerHelper_ == nullptr) { + INTELL_VOICE_LOG_ERROR("trigger helper is nullptr"); + return -1; + } + return triggerHelper_->StopGenericRecognition(uuid, callback); +} +} // namespace IntellVoiceTrigger +} // namespace OHOS \ No newline at end of file diff --git a/services/intell_voice_trigger/server/trigger_service.h b/services/intell_voice_trigger/server/trigger_service.h new file mode 100755 index 0000000..b214f82 --- /dev/null +++ b/services/intell_voice_trigger/server/trigger_service.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef INTELL_VOICE_TRIGGER_SERVICE_H +#define INTELL_VOICE_TRIGGER_SERVICE_H + +#include "trigger_db_helper.h" +#include "trigger_helper.h" + +namespace OHOS { +namespace IntellVoiceTrigger { +class TriggerService { +public: + TriggerService(); + ~TriggerService(); + void UpdateGenericTriggerModel(std::shared_ptr model); + void DeleteGenericTriggerModel(int32_t uuid); + std::shared_ptr GetGenericTriggerModel(int32_t uuid); + + int32_t StartRecognition(int32_t uuid, std::shared_ptr callback); + int32_t StopRecognition(int32_t uuid, std::shared_ptr callback); + +private: + std::shared_ptr dbHelper_ = nullptr; + std::shared_ptr triggerHelper_ = nullptr; +}; +} // namespace IntellVoiceTrigger +} // namespace OHOS +#endif \ No newline at end of file diff --git a/tests/BUILD.gn b/tests/BUILD.gn new file mode 100755 index 0000000..6a02871 --- /dev/null +++ b/tests/BUILD.gn @@ -0,0 +1,26 @@ +# Copyright (c) 2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +group("intell_voice_unit_test") { + testonly = true + deps = [ + "unittest/intell_voice_test:client_unit_test", + "unittest/intell_voice_test:trigger_manager_test", + "unittest/intell_voice_test:trigger_unit_test", + ] +} + +group("intell_voice_fuzz_test") { + testonly = true + deps = [ "fuzztest/Calculator_fuzzer:fuzztest" ] +} diff --git a/tests/fuzztest/Calculator_fuzzer/BUILD.gn b/tests/fuzztest/Calculator_fuzzer/BUILD.gn new file mode 100755 index 0000000..7367f0c --- /dev/null +++ b/tests/fuzztest/Calculator_fuzzer/BUILD.gn @@ -0,0 +1,35 @@ +# Copyright (c) 2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/config/features.gni") +import("//build/test.gni") + +module_output_path = "ai_intell_voice_framework/audio_intell_voice" + +ohos_fuzztest("CalculatorFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//foundation/ai/intelligent_voice_framework/tests/fuzztest/Calculator_fuzzer" + include_dirs = [] + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "Calculator_fuzzer.cpp" ] +} + +group("fuzztest") { + testonly = true + deps = [ ":CalculatorFuzzTest" ] +} diff --git a/tests/fuzztest/Calculator_fuzzer/Calculator_fuzzer.cpp b/tests/fuzztest/Calculator_fuzzer/Calculator_fuzzer.cpp new file mode 100755 index 0000000..0e3aae8 --- /dev/null +++ b/tests/fuzztest/Calculator_fuzzer/Calculator_fuzzer.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +const int FUZZ_DATA_LEN = 3; +const int FUZZ_FST_DATA = 0; +const int FUZZ_SND_DATA = 1; +const int FUZZ_TRD_DATA = 2; +const int FUZZ_FTH_DATA = 3; + +namespace OHOS { + bool DoSomethingInterestingWithMyAPI(const uint8_t* data, size_t size) + { + if (data == nullptr) { + return false; + } + + bool result = false; + if (size >= FUZZ_DATA_LEN) { + result = data[FUZZ_FST_DATA] == 'F' && + data[FUZZ_SND_DATA] == 'U' && + data[FUZZ_TRD_DATA] == 'Z' && + data[FUZZ_FTH_DATA] == 'Z'; + } + return result; + } +} // namespace.OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::DoSomethingInterestingWithMyAPI(data, size); + return 0; +} + diff --git a/tests/fuzztest/Calculator_fuzzer/Calculator_fuzzer.h b/tests/fuzztest/Calculator_fuzzer/Calculator_fuzzer.h new file mode 100755 index 0000000..73743ed --- /dev/null +++ b/tests/fuzztest/Calculator_fuzzer/Calculator_fuzzer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef EXAMPLE_CALCULATOR_FUZZER_H_ +#define EXAMPLE_CALCULATOR_FUZZER_H_ + +#define FUZZ_PROJECT_NAME "calculator_fuzzer" + +#endif // EXAMPLE_CALCULATOR_FUZZER_H_ \ No newline at end of file diff --git a/tests/fuzztest/Calculator_fuzzer/corpus/init b/tests/fuzztest/Calculator_fuzzer/corpus/init new file mode 100755 index 0000000..d9719ca --- /dev/null +++ b/tests/fuzztest/Calculator_fuzzer/corpus/init @@ -0,0 +1,13 @@ +# Copyright (c) 2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +FUZZ \ No newline at end of file diff --git a/tests/fuzztest/Calculator_fuzzer/project.xml b/tests/fuzztest/Calculator_fuzzer/project.xml new file mode 100755 index 0000000..4fdbc40 --- /dev/null +++ b/tests/fuzztest/Calculator_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/tests/unittest/intell_voice_test/BUILD.gn b/tests/unittest/intell_voice_test/BUILD.gn new file mode 100755 index 0000000..2bfd6d0 --- /dev/null +++ b/tests/unittest/intell_voice_test/BUILD.gn @@ -0,0 +1,110 @@ +# Copyright (c) 2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") + +module_output_path = "ai_intelligent_voice_framework/intell_voice" + +ohos_unittest("client_unit_test") { + testonly = true + module_out_path = module_output_path + sources = [ + "src/client_unit_test.cpp", + "src/engine_event_callback.cpp", + "src/wait_for_result.cpp", + ] + + include_dirs = [ + "include", + "//foundation/ai/intelligent_voice_framework/services/intell_voice_engine", + "//foundation/ai/intelligent_voice_framework/services/intell_voice_engine/server/base", + "//foundation/ai/intelligent_voice_framework/services/intell_voice_engine/proxy", + "//foundation/ai/intelligent_voice_framework/utils", + ] + + cflags_cc = [ + "-Wno-error=unused-parameter", + "-DHILOG_ENABLE", + "-DENABLE_DEBUG", + ] + + deps = [ + "//foundation/ai/intelligent_voice_framework/services:intell_voice_proxy", + ] + + external_deps = [ + "c_utils:utils", + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + "safwk:system_ability_fwk", + "samgr:samgr_proxy", + ] +} + +ohos_unittest("trigger_unit_test") { + testonly = true + module_out_path = module_output_path + sources = [ "src/trigger_unit_test.cpp" ] + + include_dirs = [ + "//foundation/ai/intelligent_voice_framework/services/intell_voice_trigger/server", + "//foundation/ai/intelligent_voice_framework/services/intell_voice_trigger/server/connector_mgr", + "//foundation/ai/intelligent_voice_framework/utils", + ] + + cflags_cc = [ + "-Wno-error=unused-parameter", + "-DHILOG_ENABLE", + "-DENABLE_DEBUG", + ] + + deps = [ + "//foundation/ai/intelligent_voice_framework/services:intell_voice_server", + ] + + external_deps = [ + "c_utils:utils", + "hiviewdfx_hilog_native:libhilog", + "relational_store:native_rdb", + ] +} + +ohos_unittest("trigger_manager_test") { + testonly = true + module_out_path = module_output_path + sources = [ "src/trigger_manager_test.cpp" ] + + include_dirs = [ + "//foundation/ai/intelligent_voice_framework/services/intell_voice_trigger/server", + "//foundation/ai/intelligent_voice_framework/services/intell_voice_trigger/server/connector_mgr", + "//foundation/ai/intelligent_voice_framework/utils", + ] + + cflags_cc = [ + "-Wno-error=unused-parameter", + "-DHILOG_ENABLE", + "-DENABLE_DEBUG", + ] + + deps = [ + "//foundation/ai/intelligent_voice_framework/services:intell_voice_server", + ] + + external_deps = [ + "c_utils:utils", + "hiviewdfx_hilog_native:libhilog", + "relational_store:native_rdb", + "safwk:system_ability_fwk", + "samgr:samgr_proxy", + ] +} diff --git a/tests/unittest/intell_voice_test/include/engine_event_callback.h b/tests/unittest/intell_voice_test/include/engine_event_callback.h new file mode 100755 index 0000000..6ce13b0 --- /dev/null +++ b/tests/unittest/intell_voice_test/include/engine_event_callback.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ENGINE_EVENT_CALLBACK_H +#define ENGINE_EVENT_CALLBACK_H + +#include "i_intell_voice_engine_callback.h" +#include "i_intell_voice_engine.h" + +namespace OHOS { +namespace IntellVoiceTests { +class EngineEventCallback : public IntellVoiceEngine::IIntellVoiceEngineEventCallback { +public: + EngineEventCallback(sptr &engine, WaitForResult *wait) + { + engine_ = engine; + waitForResult_ = wait; + } + void OnEvent(const OHOS::HDI::IntelligentVoice::Engine::V1_0::IntellVoiceEngineCallBackEvent ¶m) override; + +private: + void ReadFile(const std::string path); + +private: + int32_t startCnt_ = 0; + uint32_t pcmSize_ = 0; + sptr engine_ = nullptr; + std::shared_ptr pcmData_ = nullptr; + WaitForResult *waitForResult_; +}; +} +} +#endif \ No newline at end of file diff --git a/tests/unittest/intell_voice_test/include/wait_for_result.h b/tests/unittest/intell_voice_test/include/wait_for_result.h new file mode 100755 index 0000000..05dbfa9 --- /dev/null +++ b/tests/unittest/intell_voice_test/include/wait_for_result.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef WAIT_FOR_RESULT_H +#define WAIT_FOR_RESULT_H + +#include +#include +#include + +namespace OHOS { +namespace IntellVoiceTests { +class WaitForResult { +public: + void Wait(); + void SetIsReady(); + +private: + std::mutex mtx; + std::condition_variable condVar; + bool isReady = false; +}; +} +} +#endif \ No newline at end of file diff --git a/tests/unittest/intell_voice_test/src/client_unit_test.cpp b/tests/unittest/intell_voice_test/src/client_unit_test.cpp new file mode 100755 index 0000000..7671bed --- /dev/null +++ b/tests/unittest/intell_voice_test/src/client_unit_test.cpp @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include +#include +#include +#include + +#include "iservice_registry.h" +#include "system_ability_definition.h" +#include "intell_voice_log.h" +#include "i_intell_voice_engine.h" +#include "i_intell_voice_service.h" +#include "intell_voice_service_proxy.h" +#include "intell_voice_engine_proxy.h" +#include "engine_callback_inner.h" +#include "engine_event_callback.h" +#include "wait_for_result.h" + +using namespace OHOS::IntellVoiceTests; +using namespace OHOS::IntellVoiceEngine; +using namespace OHOS; +using namespace testing::ext; + +static sptr g_sProxy = nullptr; +#define LOG_TAG "ClientTest" + +class ClientTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + std::shared_ptr cb_ = nullptr; +}; + +void ClientTest::SetUpTestCase(void) +{ + INTELL_VOICE_LOG_INFO("hello harmony OS!\n"); +} + +void ClientTest::TearDownTestCase(void) +{ +} + +void ClientTest::SetUp(void) +{ + auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + ASSERT_NE(samgr, nullptr); + + sptr object = samgr->GetSystemAbility(INTELL_VOICE_SERVICE_ID); + ASSERT_NE(object, nullptr); + + g_sProxy = iface_cast(object); + ASSERT_NE(g_sProxy, nullptr); +} + +void ClientTest::TearDown(void) +{ +} + +HWTEST_F(ClientTest, ClientUtils, TestSize.Level1) +{ + WaitForResult waitForResult; + + sptr engine; + g_sProxy->CreateIntellVoiceEngine(INTELL_VOICE_ENROLL, engine); + ASSERT_NE(engine, nullptr); + + sptr callback = new(std::nothrow) EngineCallbackInner(); + ASSERT_NE(callback, nullptr); + cb_ = std::make_shared(engine, &waitForResult); + ASSERT_NE(cb_, nullptr); + + callback->SetEngineEventCallback(cb_); + sptr callbackObj = callback->AsObject(); + ASSERT_NE(callbackObj, nullptr); + + engine->SetCallback(callbackObj); + + IntellVoiceEngineInfo info = {}; + info.wakeupPhrase = "\xE5\xB0\x8F\xE8\x89\xBA\xE5\xB0\x8F\xE8\x89\xBA"; + info.isPcmFromExternal = true; + info.minBufSize = 1280; + info.sampleChannels = 1; + info.bitsPerSample = 16; + info.sampleRate = 16000; + + engine->Attach(info); + + waitForResult.Wait(); + + engine->Detach(); + + INTELL_VOICE_LOG_INFO("end\n"); +} diff --git a/tests/unittest/intell_voice_test/src/engine_event_callback.cpp b/tests/unittest/intell_voice_test/src/engine_event_callback.cpp new file mode 100755 index 0000000..31e6221 --- /dev/null +++ b/tests/unittest/intell_voice_test/src/engine_event_callback.cpp @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include +#include + +#include "intell_voice_log.h" +#include "engine_event_callback.h" + +using namespace std; + +#define LOG_TAG "EngineEventCallback" + +namespace { +constexpr int32_t ENROLL_CNT = 3; +static constexpr uint32_t BUFFER_SIZE = 1280; +} + +namespace OHOS { +namespace IntellVoiceTests { +const std::string TEST_RESOURCE_PATH = "/data/test/resource/"; + +void EngineEventCallback::OnEvent( + const OHOS::HDI::IntelligentVoice::Engine::V1_0::IntellVoiceEngineCallBackEvent &event) +{ + INTELL_VOICE_LOG_INFO("OnEvent EngineCallBackInfo: msgId: %{public}d, errCode: %{public}d, context: %{public}s", + event.msgId, + event.result, + event.info.c_str()); + + if (event.msgId == HDI::IntelligentVoice::Engine::V1_0::INTELL_VOICE_ENGINE_MSG_INIT_DONE) { + EXPECT_EQ(event.result, HDI::IntelligentVoice::Engine::V1_0::INTELL_VOICE_ENGINE_OK); + startCnt_ = 1; + engine_->Start(false); + EngineEventCallback::ReadFile(TEST_RESOURCE_PATH + "one.pcm"); + } + + if (event.msgId == HDI::IntelligentVoice::Engine::V1_0::INTELL_VOICE_ENGINE_MSG_ENROLL_COMPLETE) { + EXPECT_EQ(event.result, HDI::IntelligentVoice::Engine::V1_0::INTELL_VOICE_ENGINE_OK); + if (startCnt_ < ENROLL_CNT) { + ++startCnt_; + engine_->Start(startCnt_ == ENROLL_CNT ? true : false); + if (startCnt_ == ENROLL_CNT) { + EngineEventCallback::ReadFile(TEST_RESOURCE_PATH + "three.pcm"); + } else { + EngineEventCallback::ReadFile(TEST_RESOURCE_PATH + "two.pcm"); + } + } else if (startCnt_ == ENROLL_CNT) { + engine_->SetParameter("CommitEnrollment=true"); + } + } + + if (event.msgId == HDI::IntelligentVoice::Engine::V1_0::INTELL_VOICE_ENGINE_MSG_COMMIT_ENROLL_COMPLETE) { + EXPECT_EQ(event.result, HDI::IntelligentVoice::Engine::V1_0::INTELL_VOICE_ENGINE_OK); + waitForResult_->SetIsReady(); + } +} + +void EngineEventCallback::ReadFile(const std::string path) +{ + INTELL_VOICE_LOG_INFO("path: %{public}s", path.c_str()); + ifstream infile; + infile.open(path, ios::in | ios::binary); + + if (!infile.is_open()) { + INTELL_VOICE_LOG_INFO("open file failed"); + } + + infile.seekg(0, infile.end); + pcmSize_ = static_cast(infile.tellg()); + pcmData_ = std::shared_ptr(new uint8_t[pcmSize_], [](uint8_t *p) { delete[] p; }); + if (pcmData_ == nullptr) { + INTELL_VOICE_LOG_INFO("pcmData_ is null"); + return; + } + INTELL_VOICE_LOG_INFO("read pcm, pcmSize:%u", pcmSize_); + infile.seekg(0, infile.beg); + infile.read(reinterpret_cast(pcmData_.get()), pcmSize_); + infile.close(); + + for (uint32_t i = 0; i < pcmSize_ / BUFFER_SIZE; i++) { + engine_->WriteAudio(pcmData_.get() + i * BUFFER_SIZE, BUFFER_SIZE); + } + engine_->SetParameter("end_of_pcm=true"); +} +} // namespace IntellVoiceTests +} // namespace OHOS diff --git a/tests/unittest/intell_voice_test/src/trigger_manager_test.cpp b/tests/unittest/intell_voice_test/src/trigger_manager_test.cpp new file mode 100755 index 0000000..0401159 --- /dev/null +++ b/tests/unittest/intell_voice_test/src/trigger_manager_test.cpp @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include +#include + +#include +#include "intell_voice_log.h" + +#include "trigger_manager.h" +#include "trigger_base_type.h" +#include "trigger_detector_callback.h" + +#define LOG_TAG "TriggerManagerTest" + +using namespace OHOS::IntellVoiceTrigger; +using namespace OHOS; +using namespace testing::ext; +using namespace std; + +static std::shared_ptr triggerManager = nullptr; + +class TriggerManagerTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + void TriggerManagerTestCallBack(); + void ReadFile(const std::string path); + std::vector modelData; + bool testResult = false; +}; + +void TriggerManagerTest::SetUpTestCase(void) +{} + +void TriggerManagerTest::TearDownTestCase(void) +{} + +void TriggerManagerTest::SetUp(void) +{ + triggerManager = TriggerManager::GetInstance(); + ASSERT_NE(triggerManager, nullptr); + ReadFile("/data/test/resource/model_one.txt"); +} + +void TriggerManagerTest::TearDown(void) +{ + triggerManager = nullptr; +} + +void TriggerManagerTest::TriggerManagerTestCallBack(void) +{ + INTELL_VOICE_LOG_INFO("enter"); + testResult = true; +} + +void TriggerManagerTest::ReadFile(const std::string path) +{ + INTELL_VOICE_LOG_INFO("path: %{public}s", path.c_str()); + ifstream infile; + infile.open(path, ios::in); + + if (!infile.is_open()) { + INTELL_VOICE_LOG_INFO("open file failed"); + } + + infile.seekg(0, infile.end); + uint32_t modelSize = static_cast(infile.tellg()); + std::vector datas(modelSize); + infile.seekg(0, infile.beg); + infile.read(reinterpret_cast(datas.data()), modelSize); + infile.close(); + + modelData = datas; +} + +HWTEST_F(TriggerManagerTest, start_recognition_001, TestSize.Level1) +{ + int32_t uuid = 11; + auto model = std::make_shared(uuid, 100); + model->SetData(modelData); + triggerManager->UpdateModel(model); + + std::shared_ptr cb = std::make_shared( + std::bind(&TriggerManagerTest::TriggerManagerTestCallBack, this)); + auto detector = triggerManager->CreateTriggerDetector(uuid, cb); + sleep(1); + detector->StartRecognition(); + triggerManager->DeleteModel(uuid); + + EXPECT_EQ(true, testResult); +} diff --git a/tests/unittest/intell_voice_test/src/trigger_unit_test.cpp b/tests/unittest/intell_voice_test/src/trigger_unit_test.cpp new file mode 100755 index 0000000..f96c850 --- /dev/null +++ b/tests/unittest/intell_voice_test/src/trigger_unit_test.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include + +#include "intell_voice_log.h" +#include "trigger_manager.h" +#include "trigger_base_type.h" +#include "trigger_detector_callback.h" + +#define LOG_TAG "TriggerTest" + +using namespace OHOS::IntellVoiceTrigger; +using namespace OHOS; +using namespace testing::ext; + +static std::shared_ptr triggerManager = nullptr; + +class TriggerTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void TriggerTest::SetUpTestCase(void) +{} + +void TriggerTest::TearDownTestCase(void) +{} + +void TriggerTest::SetUp(void) +{ + triggerManager = TriggerManager::GetInstance(); + ASSERT_NE(triggerManager, nullptr); +} + +void TriggerTest::TearDown(void) +{ + triggerManager = nullptr; +} + +HWTEST_F(TriggerTest, trigger_db_helper_001, TestSize.Level1) +{ + // insert model + int32_t uuid = 11; + auto model = std::make_shared(uuid, 100); + uint8_t data[4] = {0, 1, 2, 3}; + model->SetData(data, sizeof(data)); + + std::vector expect(sizeof(data)); + memcpy(&expect[0], data, sizeof(data)); + + triggerManager->UpdateModel(model); + auto result = triggerManager->GetModel(uuid); + EXPECT_EQ(expect, result->GetData()); + + // update model + uint8_t newdata[4] = {0, 1, 2, 5}; + model->SetData(newdata, sizeof(newdata)); + + expect.clear(); + expect.resize(sizeof(newdata)); + memcpy(&expect[0], newdata, sizeof(newdata)); + + triggerManager->UpdateModel(model); + result = triggerManager->GetModel(uuid); + EXPECT_EQ(expect, result->GetData()); + + // delete model + triggerManager->DeleteModel(uuid); + result = triggerManager->GetModel(uuid); + EXPECT_EQ(nullptr, result); +} + diff --git a/tests/unittest/intell_voice_test/src/wait_for_result.cpp b/tests/unittest/intell_voice_test/src/wait_for_result.cpp new file mode 100755 index 0000000..7883f3c --- /dev/null +++ b/tests/unittest/intell_voice_test/src/wait_for_result.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "wait_for_result.h" +#include "intell_voice_log.h" + +#define LOG_TAG "WaitForResult" + +namespace OHOS { +namespace IntellVoiceTests { +void WaitForResult::Wait() +{ + std::unique_lock lock(mtx); + condVar.wait(lock, [this] {return isReady;}); +} + +void WaitForResult::SetIsReady() +{ + { + std::lock_guard lock(mtx); + isReady = true; + } + INTELL_VOICE_LOG_INFO("notify_one"); + condVar.notify_one(); +} +} +} diff --git a/utils/BUILD.gn b/utils/BUILD.gn new file mode 100755 index 0000000..9bc07e5 --- /dev/null +++ b/utils/BUILD.gn @@ -0,0 +1,68 @@ +# Copyright (c) 2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") + +ohos_shared_library("intell_voice_utils") { + configs = [ "//build/config/compiler:exceptions" ] + + include_dirs = [ "//foundation/ai/intelligent_voice_framework/utils" ] + + sources = [ + "base_thread.cpp", + "memory_guard.cpp", + "message_queue.cpp", + "msg_handle_thread.cpp", + "string_util.cpp", + "time_util.cpp", + ] + + defines = [] + if (use_musl) { + if (use_jemalloc && use_jemalloc_dfx_intf) { + defines += [ "CONFIG_USE_JEMALLOC_DFX_INTF" ] + } + } + + external_deps = [ + "c_utils:utils", + "hiviewdfx_hilog_native:libhilog", + ] + + cflags = [ + "-Wall", + "-Wextra", + "-Werror", + "-DHAVE_CONFIG_H", + "-fno-strict-aliasing", + "-Wno-sign-compare", + "-Wno-builtin-requires-header", + "-Wno-implicit-function-declaration", + "-Wno-format", + "-Wno-int-conversion", + "-Wno-unused-function", + "-Wno-unused-parameter", + "-Wno-thread-safety-attributes", + "-Wno-inconsistent-missing-override", + "-fno-rtti", + "-fno-exceptions", + "-ffunction-sections", + "-fdata-sections", + "-Wheader-hygiene", + ] + + ldflags = [ "-Wl" ] + + subsystem_name = "ai" + part_name = "intelligent_voice_framework" +} diff --git a/utils/base_constants.h b/utils/base_constants.h new file mode 100755 index 0000000..b96b9db --- /dev/null +++ b/utils/base_constants.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef BASE_CONSTANTS_H +#define BASE_CONSTANTS_H + +#include + +namespace OHOS { +namespace IntellVoiceUtils { +const int32_t H_PER_MIN = 60; +const int32_t MIN_PER_S = 60; +const int32_t S_PER_MS = 1000; +const int32_t MS_PER_US = 1000; +const int32_t US_PER_NS = 1000; + +const uint32_t MB_PER_KB = 1024; +const uint32_t KB_PER_B = 1024; +} +} +#endif diff --git a/utils/base_thread.cpp b/utils/base_thread.cpp new file mode 100755 index 0000000..84df145 --- /dev/null +++ b/utils/base_thread.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "base_thread.h" +#include +#include "intell_voice_log.h" + +#define LOG_TAG "BaseThread" + +using namespace std; + +namespace OHOS { +namespace IntellVoiceUtils { +BaseThread::BaseThread() : tid(0), isRuning(false) +{ +} + +BaseThread::~BaseThread() +{ + if (isRuning) { + pthread_detach(tid); + } +} + +void *BaseThread::RunInThread(void *arg) +{ + BaseThread *pt = static_cast(arg); + pt->Run(); + + return nullptr; +} + +void BaseThread::Start() +{ + std::lock_guard lock(mutex_); + + int ret = pthread_create(&tid, nullptr, BaseThread::RunInThread, this); + if (ret != 0) { + INTELL_VOICE_LOG_ERROR("create thread failed"); + return; + } + + isRuning = true; +} + +void BaseThread::Join() +{ + std::lock_guard lock(mutex_); + + if (!isRuning) { + return; + } + + pthread_join(tid, nullptr); + isRuning = false; +} + +bool BaseThread::IsRuning() const +{ + return isRuning; +} + +pid_t BaseThread::Gettid() const +{ + return tid; +} +} +} diff --git a/utils/base_thread.h b/utils/base_thread.h new file mode 100755 index 0000000..2f8764c --- /dev/null +++ b/utils/base_thread.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef BASE_THREAD_H +#define BASE_THREAD_H + +#include +#include +#include +#include + +namespace OHOS { +namespace IntellVoiceUtils { +class BaseThread { +public: + BaseThread(); + virtual ~BaseThread(); + + void Start(); + void Join(); + bool IsRuning() const; + + pid_t Gettid() const; + +protected: + virtual void Run() = 0; + +private: + static void *RunInThread(void *arg); + pthread_t tid; + bool isRuning; + std::mutex mutex_ {}; +}; +} +} +#endif diff --git a/utils/intell_voice_generic_factory.h b/utils/intell_voice_generic_factory.h new file mode 100755 index 0000000..6e6829f --- /dev/null +++ b/utils/intell_voice_generic_factory.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTELL_VOICE_GENERIC_FACTORY_H +#define INTELL_VOICE_GENERIC_FACTORY_H +#include + +namespace OHOS { +namespace IntellVoiceUtils { +template +class UniquePtrFactory { +public: + using UniqueProductPtr = std::unique_ptr; + + template + static UniqueProductPtr CreateInstance(Args && ...args) + { + T *instance = new(std::nothrow) T {}; + if (instance == nullptr) { + return UniqueProductPtr {nullptr, nullptr}; + } + if (!instance->Init(std::forward(args)...)) { + delete instance; + return UniqueProductPtr {nullptr, nullptr}; + } + return UniqueProductPtr(instance, DestroyInstance); + } + +private: + static void DestroyInstance(T *ptr) + { + delete ptr; + } +}; + +template +using UniqueProductType = typename UniquePtrFactory::UniqueProductPtr; + +template +class SptrFactory { +public: + using SptrProductPtr = OHOS::sptr; + + template + static SptrProductPtr CreateInstance(Args && ...args) + { + T *instance = new(std::nothrow) T {}; + if (instance == nullptr) { + return SptrProductPtr { nullptr }; + } + if (!instance->Init(std::forward(args)...)) { + delete instance; + return SptrProductPtr { nullptr }; + } + return SptrProductPtr(instance); + } +}; + +template +using SptrProductType = typename SptrFactory::ProductPtr; +} +} +#endif diff --git a/utils/intell_voice_log.h b/utils/intell_voice_log.h new file mode 100755 index 0000000..627c1c2 --- /dev/null +++ b/utils/intell_voice_log.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef INTELL_VOICE_LOG_H +#define INTELL_VOICE_LOG_H + +#include +#include "hilog/log.h" + +#undef LOG_DOMAIN +#define LOG_DOMAIN 0xD002500 +#undef LOG_TAG + +#define INTELL_VOICE_LOG_DEBUG(fmt, ...) \ + HILOG_DEBUG(LOG_CORE, "[%{public}s:%{public}d]: " fmt, __func__, __LINE__, ##__VA_ARGS__) +#define INTELL_VOICE_LOG_ERROR(fmt, ...) \ + HILOG_ERROR(LOG_CORE, "[%{public}s:%{public}d]: " fmt, __func__, __LINE__, ##__VA_ARGS__) +#define INTELL_VOICE_LOG_WARN(fmt, ...) \ + HILOG_WARN(LOG_CORE, "[%{public}s:%{public}d]: " fmt, __func__, __LINE__, ##__VA_ARGS__) +#define INTELL_VOICE_LOG_INFO(fmt, ...) \ + HILOG_INFO(LOG_CORE, "[%{public}s:%{public}d]: " fmt, __func__, __LINE__, ##__VA_ARGS__) +#define INTELL_VOICE_LOG_FATAL(fmt, ...) \ + HILOG_FATAL(LOG_CORE, "[%{public}s:%{public}d]: " fmt, __func__, __LINE__, ##__VA_ARGS__) + +#endif diff --git a/utils/memory_guard.cpp b/utils/memory_guard.cpp new file mode 100755 index 0000000..6e84b0b --- /dev/null +++ b/utils/memory_guard.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "memory_guard.h" +#include +#include +#include "intell_voice_log.h" + +#define LOG_TAG "MemoryGaurd" + +namespace OHOS { +namespace IntellVoiceUtils { +MemoryGuard::MemoryGuard() +{ +#ifdef CONFIG_USE_JEMALLOC_DFX_INTF + // 0 indicates success + int32_t ret1 = mallopt(M_SET_THREAD_CACHE, M_THREAD_CACHE_DISABLE); + int32_t ret2 = mallopt(M_DELAYED_FREE, M_DELAYED_FREE_DISABLE); + INTELL_VOICE_LOG_INFO("disable tcache and delay free, result:%{public}d, %{public}d", ret1, ret2); +#endif +} + +MemoryGuard::~MemoryGuard() +{ +#ifdef CONFIG_USE_JEMALLOC_DFX_INTF + int32_t err = mallopt(M_FLUSH_THREAD_CACHE, 0); + INTELL_VOICE_LOG_INFO("flush cache, result: %{public}d", err); +#endif +} +} +} \ No newline at end of file diff --git a/utils/memory_guard.h b/utils/memory_guard.h new file mode 100755 index 0000000..fecf4d0 --- /dev/null +++ b/utils/memory_guard.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MEMORY_GUARD +#define MEMORY_GUARD + +namespace OHOS { +namespace IntellVoiceUtils { +class MemoryGuard final { +public: + MemoryGuard(); + ~MemoryGuard(); +}; +} +} +#endif \ No newline at end of file diff --git a/utils/message_queue.cpp b/utils/message_queue.cpp new file mode 100755 index 0000000..020b1da --- /dev/null +++ b/utils/message_queue.cpp @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "message_queue.h" +#include "intell_voice_log.h" + +#define LOG_TAG "MesaageQueue" + +using namespace std; + +namespace OHOS { +namespace IntellVoiceUtils { +Message::Message(uint32_t what) +{ + mWhat = what; + arg1 = 0; + arg2 = 0; +} + +Message::Message(uint32_t what, int32_t arg1) +{ + mWhat = what; + this->arg1 = arg1; +} + +Message::Message(uint32_t what, int32_t arg1, int32_t arg2, float arg3) +{ + mWhat = what; + this->arg1 = arg1; + this->arg2 = arg2; + this->arg3 = arg3; +} + +Message::Message(uint32_t what, int32_t arg1, int32_t arg2, string obj) +{ + mWhat = what; + this->arg1 = arg1; + this->arg2 = arg2; + this->obj = obj; +} + +Message::Message(uint32_t what, int32_t arg1, int32_t arg2, float arg3, string obj) +{ + mWhat = what; + this->arg1 = arg1; + this->arg2 = arg2; + this->arg3 = arg3; + this->obj = obj; +} + +Message::Message(uint32_t what, std::shared_ptr obj2) +{ + mWhat = what; + this->obj2 = obj2; +} + +Message::Message(uint32_t what, std::shared_ptr obj2, std::shared_ptr obj3) +{ + mWhat = what; + this->obj2 = obj2; + this->obj3 = obj3; +} + +Message::Message(uint32_t what, void* voidPtr) +{ + mWhat = what; + this->voidPtr = voidPtr; +} + +Message::Message(uint32_t what, void* voidPtr, int32_t arg1) +{ + mWhat = what; + this->voidPtr = voidPtr; + this->arg1 = arg1; +} + +Message::~Message() +{ + voidPtr = nullptr; +} + +MessageQueue::MessageQueue(uint32_t size) +{ + mSize = size; + mLock = PTHREAD_MUTEX_INITIALIZER; + pthread_condattr_t attr; + int result = pthread_condattr_init(&attr); + result += pthread_cond_init(&mCond, &attr); + result += pthread_condattr_destroy(&attr); + if (result != 0) { + INTELL_VOICE_LOG_ERROR("message queue construct init cond failed"); + } +} + +MessageQueue::~MessageQueue() +{ + int result = pthread_mutex_destroy(&mLock); + result += pthread_cond_destroy(&mCond); + if (result != 0) { + INTELL_VOICE_LOG_ERROR("message queue deconstruct destroy cond failed"); + } +} + +shared_ptr MessageQueue::ReceiveMsg() +{ + shared_ptr msg = nullptr; + pthread_mutex_lock(&mLock); + while (mQueue.empty()) { + pthread_cond_wait(&mCond, &mLock); + } + + msg = mQueue.front(); + mQueue.pop(); + pthread_mutex_unlock(&mLock); + + return msg; +} + +bool MessageQueue::SendMsg(shared_ptr msg) +{ + pthread_mutex_lock(&mLock); + if (static_cast(mQueue.size()) >= mSize || msg == nullptr) { + INTELL_VOICE_LOG_WARN("send message failed, msg queue full(qsize %{public}d)", static_cast(mQueue.size())); + pthread_mutex_unlock(&mLock); + return false; + } + + try { + mQueue.push(msg); + } catch (const std::length_error& err) { + INTELL_VOICE_LOG_ERROR("messagequeue push, length error"); + pthread_mutex_unlock(&mLock); + return false; + } + + pthread_cond_signal(&mCond); + pthread_mutex_unlock(&mLock); + + return true; +} + +void MessageQueue::Clear() +{ + pthread_mutex_lock(&mLock); + while (!mQueue.empty()) { + mQueue.pop(); + } + pthread_mutex_unlock(&mLock); +} +} +} diff --git a/utils/message_queue.h b/utils/message_queue.h new file mode 100755 index 0000000..5101b24 --- /dev/null +++ b/utils/message_queue.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MESSAGE_QUEUE_H +#define MESSAGE_QUEUE_H + +#include +#include +#include +#include +#include +#include +#include "nocopyable.h" + +namespace OHOS { +namespace IntellVoiceUtils { +struct SynInfo { + std::mutex mMutex; + std::condition_variable mCV; +}; +struct Message { +public: + explicit Message(uint32_t what); + Message(uint32_t what, int32_t arg1); + Message(uint32_t what, int32_t arg1, int32_t arg2, float arg3); + Message(uint32_t what, int32_t arg1, int32_t arg2, std::string obj); + Message(uint32_t what, int32_t arg1, int32_t arg2, float arg3, std::string obj); + Message(uint32_t what, std::shared_ptr obj2); + Message(uint32_t what, std::shared_ptr obj2, std::shared_ptr obj3); + Message(uint32_t what, void* voidPtr); + Message(uint32_t what, void* voidPtr, int32_t arg1); + ~Message(); + + uint32_t mWhat { 0 }; + int32_t arg1 { 0 }; + int32_t arg2 { 0 }; + float arg3 { 0.0 }; + std::string obj; + std::shared_ptr obj2 { nullptr }; + std::shared_ptr obj3 { nullptr }; + void* voidPtr { nullptr }; + uint32_t mCallbackId { 0 }; + + std::shared_ptr result { nullptr }; +}; + +class MessageQueue { +public: + explicit MessageQueue(uint32_t size); + ~MessageQueue(); + std::shared_ptr ReceiveMsg(); + bool SendMsg(std::shared_ptr msg); + void Clear(); + +private: + DISALLOW_COPY(MessageQueue); + DISALLOW_MOVE(MessageQueue); + + uint32_t mSize; + pthread_mutex_t mLock; + pthread_cond_t mCond; + std::queue> mQueue; +}; +} +} +#endif diff --git a/utils/msg_handle_thread.cpp b/utils/msg_handle_thread.cpp new file mode 100755 index 0000000..3fb208e --- /dev/null +++ b/utils/msg_handle_thread.cpp @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "msg_handle_thread.h" +#include +#include +#include "intell_voice_log.h" + +#define LOG_TAG "MsgHandleThread" + +using namespace std; + +namespace OHOS { +namespace IntellVoiceUtils { +static const uint32_t MSQ_QUEUE_MAX_LEN = 100; +static const int32_t MSG_MAX_SYNC_TIMEOUT = 5; + +MsgHandleThread::MsgHandleThread() : msgQue(MSQ_QUEUE_MAX_LEN), callbackThread(nullptr) {} + +MsgHandleThread::MsgHandleThread(std::shared_ptr callbackMsgQue) + : callbackMsgQue(callbackMsgQue), msgQue(MSQ_QUEUE_MAX_LEN), callbackThread(nullptr) +{} + +MsgHandleThread::MsgHandleThread(MsgHandleThread *callbackThread) + : msgQue(MSQ_QUEUE_MAX_LEN), callbackThread(callbackThread) +{} + +MsgHandleThread::~MsgHandleThread() {} + +void MsgHandleThread::SetCallbackThread(MsgHandleThread *tmpCallbackThread) +{ + callbackThread = tmpCallbackThread; +} + +// the default realization is for debug, subclass should override this func +bool MsgHandleThread::HandleMsg(Message &msg) +{ + INTELL_VOICE_LOG_INFO("run thread %u process msg %u", Gettid(), msg.mWhat); + + SendbackMsg(msg); + + return true; +} + +bool MsgHandleThread::SendMsg(Message msg) +{ + try { + msgQue.SendMsg(std::make_shared(msg)); + } catch (const std::length_error& err) { + INTELL_VOICE_LOG_ERROR("length error"); + return false; + } + + return true; +} + +bool MsgHandleThread::SendMsg(std::shared_ptr msg) +{ + if (msg == nullptr) { + return false; + } + + msgQue.SendMsg(msg); + return true; +} + +bool MsgHandleThread::SendSynMsg(shared_ptr msg) +{ + if (msg == nullptr) { + return false; + } + + msg->result = std::make_shared(); + if (msg->result == nullptr) { + INTELL_VOICE_LOG_ERROR("create sync info failed"); + return false; + } + + unique_lock lock(msg->result->mMutex); + msgQue.SendMsg(msg); + if (msg->result->mCV.wait_for(lock, chrono::seconds(MSG_MAX_SYNC_TIMEOUT)) == std::cv_status::no_timeout) { + return true; + } else { + INTELL_VOICE_LOG_WARN("send syn msg timeout"); + return false; + } +} + +void MsgHandleThread::SendbackMsg(Message msg) +{ + if (callbackThread != nullptr) { + callbackThread->SendMsg(msg); + } + + if (callbackMsgQue != nullptr) { + callbackMsgQue->SendMsg(make_shared(msg)); + } +} + +void MsgHandleThread::Run() +{ + bool isQuit = false; + + while (!isQuit) { + shared_ptr msg = msgQue.ReceiveMsg(); + + isQuit = HandleMsg(*msg); + + if (msg->result != nullptr) { + unique_lock lock(msg->result->mMutex); + msg->result->mCV.notify_all(); + } + } +} + +string MsgHandleThread::ToString() const +{ + return ""; +} +} +} diff --git a/utils/msg_handle_thread.h b/utils/msg_handle_thread.h new file mode 100755 index 0000000..b22cd8c --- /dev/null +++ b/utils/msg_handle_thread.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MSG_HANDLE_THREAD_H +#define MSG_HANDLE_THREAD_H + +#include +#include "message_queue.h" +#include "base_thread.h" + +namespace OHOS { +namespace IntellVoiceUtils { +class MsgHandleThread : public BaseThread { +public: + MsgHandleThread(); + // for compatible with wakeup engine + explicit MsgHandleThread(std::shared_ptr callbackMsgQue); + explicit MsgHandleThread(MsgHandleThread *callbackThread); + ~MsgHandleThread() override; + bool SendMsg(Message msg); + bool SendMsg(std::shared_ptr msg); + bool SendSynMsg(std::shared_ptr msg); + void SetCallbackThread(MsgHandleThread *tmpCallbackThread); + // for debug + std::string ToString() const; + +protected: + // subclass should override this function most time + virtual bool HandleMsg(Message &msg); + virtual void SendbackMsg(Message msg); + +private: + void Run() override; + + std::shared_ptr callbackMsgQue { nullptr }; + MessageQueue msgQue; + MsgHandleThread *callbackThread; +}; +} +} +#endif diff --git a/utils/scope_guard.h b/utils/scope_guard.h new file mode 100755 index 0000000..9e364a7 --- /dev/null +++ b/utils/scope_guard.h @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef SCOPE_GUARD_H +#define SCOPE_GUARD_H + +#include + +namespace OHOS { +namespace IntellVoiceUtils { +template +class ScopeGuard { +public: + ScopeGuard(Func &&f) : mFunc(std::forward(f)), mActive(true) + { + } + + ScopeGuard(ScopeGuard &&rhs) : mFunc(std::move(rhs.mFunc)), mActive(rhs.mActive) + { + rhs.Disable(); + } + + ~ScopeGuard() + { + if (mActive) { + mFunc(); + } + } + + void Disable() + { + mActive = false; + } + + bool Active() const + { + return mActive; + } + + void EarlyExit() + { + if (mActive) { + mFunc(); + } + mActive = false; + } +private: + Func mFunc; + bool mActive; + ScopeGuard() = delete; + ScopeGuard(const ScopeGuard &) = delete; + ScopeGuard &operator=(const ScopeGuard &) = delete; + ScopeGuard &operator=(ScopeGuard &&) = delete; +}; + +// tag dispatch +struct ScopeGuardOnExit {}; + +template +inline ScopeGuard operator+(ScopeGuardOnExit, Func &&fn) +{ + return ScopeGuard(std::forward(fn)); +} +} +} + +/*** ScopeGuard ensure the specified function which is created by ON_SCOPE_EXIT is executed no matter how the current +**** scope exit. +**** when use ON_SCOPE_EXIT macro, the format is: +**** ON_SCOPE_EXIT { +********your code +**** }; +*/ +#define ON_SCOPE_EXIT \ + auto __onScopeGuardExit__ = OHOS::IntellVoiceUtils::ScopeGuardOnExit() + [&]() + +#define CANCEL_SCOPE_EXIT \ + (__onScopeGuardExit__.Disable()) + +#define EARLY_SCOPE_EXIT \ + (__onScopeGuardExit__.EarlyExit()) + +#define ON_SCOPE_EXIT_WITH_NAME(variable_name) \ + auto variable_name = OHOS::IntellVoiceUtils::ScopeGuardOnExit() + [&]() + +#endif diff --git a/utils/string_util.cpp b/utils/string_util.cpp new file mode 100755 index 0000000..ec0c8ea --- /dev/null +++ b/utils/string_util.cpp @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "string_util.h" +#include +#include +#include +#include +#include "intell_voice_log.h" + +#undef LOG_TAG +#define LOG_TAG "StringUtil" + +using namespace std; + +namespace OHOS { +namespace IntellVoiceUtils { +static const char16_t DELIMITER_EQUAL_SIGN = '='; + +// #ABC#WWW##XYZ#---->vector[0]: ABC, vector[1]: WWW, vector[2]: XYZ +void StringUtil::Split(const string &str, const string &sep, vector &res) +{ + res.clear(); + string tmpStr = str; + unsigned int startPos = 0; + size_t findPos = tmpStr.find(sep, startPos); + while (findPos != string::npos) { + if (findPos > startPos) { + res.push_back(tmpStr.substr(static_cast(startPos), static_cast((findPos - startPos)))); + } + startPos = findPos + sep.length(); + findPos = tmpStr.find(sep, startPos); + } + + if (startPos < tmpStr.length()) { + res.push_back(tmpStr.substr(startPos)); + } +} + +// the func is called for AcousticPruner and AcousticPrunerExtra file +std::vector StringUtil::StringSplit(string &str, const string &pattern) +{ + string::size_type pos; + vector result; + str += pattern; + unsigned int size = str.size(); + + for (unsigned int i = 0; i < size; i++) { + pos = str.find(pattern, i); + if (pos < size) { + string s = str.substr(i, pos - i); + result.push_back(s); + i = pos + pattern.size() - 1; + } + } + + return result; +} + +template string StringUtil::PrintVector(vector &array, string &delimiter) +{ + if (array.empty()) { + return ""; + } + + ostringstream oss; + copy(array.begin(), array.end() - 1, ostream_iterator(oss, delimiter.c_str())); + oss << array.back(); + + return oss.str(); +} + +void StringUtil::TrimSpecialChars(string &str) +{ + size_t sp = 0; + + while (sp < str.size()) { + size_t ep = str.find_first_of(" \t\n\v\f\r,.:;!~@#$%^&*()`?/-+", sp); + if (ep != string::npos) { + str.erase(ep, 1); + sp = ep; + } else { + break; + } + } +} + +uint32_t StringUtil::CalSubStrNum(const string &str, const string &subStr) +{ + if (subStr.size() == 0) { + return 0; + } + uint32_t count = 0; + string::size_type pos = 0; + pos = str.find(subStr, pos); + while (pos != string::npos) { + count++; + pos = pos + subStr.size(); + pos = str.find(subStr, pos); + } + + return count; +} +bool StringUtil::SplitLineToPair(const std::string &line, std::string &first, std::string &second) +{ + if (line.empty()) { + INTELL_VOICE_LOG_ERROR("line is empty"); + return false; + } + // pinyin:words + size_t pos = line.find(DELIMITER_EQUAL_SIGN); + // not find delimiter or it is the last char. + if (string::npos == pos || (line.length() - 1) == pos) { + return false; + } + + first = line.substr(0, pos); + second = line.substr(pos + 1, string::npos); + // trim left and right spaces. + Trim(first); + Trim(second); + + if (first.empty() || second.empty()) { + INTELL_VOICE_LOG_ERROR("line is invalid, first:%s, second:%s", first.c_str(), second.c_str()); + return false; + } + return true; +} +} +} + diff --git a/utils/string_util.h b/utils/string_util.h new file mode 100755 index 0000000..dca1324 --- /dev/null +++ b/utils/string_util.h @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef STRING_UTIL_H +#define STRING_UTIL_H + +#include +#include +#include +#include "nocopyable.h" +#include "securec.h" + +namespace OHOS { +namespace IntellVoiceUtils { +class StringUtil { +public: + StringUtil() {} + ~StringUtil() {} + static void Split(const std::string &str, const std::string &sep, std::vector &res); + static std::vector StringSplit(std::string &str, const std::string &pattern); + static void TrimL(std::string &str); + static void TrimR(std::string &str); + static void Trim(std::string &str); + template static std::string PrintVector(std::vector &array, std::string &delimiter); + static std::string Float2String(float arg, int32_t precision = 6); + static std::string Int2String(int32_t arg); + static void StringToLower(std::string &str); + static std::string StringToUpper(const std::string &str); + static std::string StringToUpperX(const std::string &str); + static void TrimSpecialChars(std::string &str); + static uint32_t CalSubStrNum(const std::string &str, const std::string &subStr); + static bool SplitLineToPair(const std::string &line, std::string &first, std::string &second); + +private: + DISALLOW_COPY_AND_MOVE(StringUtil); +}; + +// remove space of left side, ascii +inline void StringUtil::TrimL(std::string &str) +{ + size_t p = str.find_first_not_of(" \t\n\v\f\r"); + if (p == std::string::npos) { + str.clear(); + } else { + str = str.substr(p); + } +} + +// remove space of right side, ascii +inline void StringUtil::TrimR(std::string &str) +{ + size_t p = str.find_last_not_of(" \t\n\v\f\r"); + if (p == std::string::npos) { + str.clear(); + } else { + str.erase(p + 1); + } +} + +// remove space of both side, ascii +inline void StringUtil::Trim(std::string &str) +{ + TrimL(str); + TrimR(str); +} + +inline std::string StringUtil::Float2String(float arg, int32_t precision) +{ + // warning -- local variable 'score' declared not subsequently referenced is false alarm, ignore + char score[100] = {'\0'}; //lint !e529 + if (sprintf_s(score, sizeof(score), "%.*f", precision, arg) == -1) { + return ""; + } + + return std::string(score); +} + +inline std::string StringUtil::Int2String(int32_t arg) +{ + static const int32_t RPESICION = 9; + std::stringstream ss; + + ss.precision(RPESICION); + ss << arg; + + return ss.str(); +} + +inline void StringUtil::StringToLower(std::string &str) +{ + for (uint32_t k = 0; k < str.size(); k++) { + str[k] = static_cast(tolower(str[k])); + } +} + +inline std::string StringUtil::StringToUpper(const std::string &str) +{ + std::string upstr = str; + for (uint32_t k = 0; k < str.size(); k++) { + upstr[k] = static_cast(toupper(str[k])); + } + + return upstr; +} + +inline std::string StringUtil::StringToUpperX(const std::string &str) +{ + std::string upstr = str; + for (uint32_t i = 0; i < upstr.size(); i++) { + if (upstr[i] <= 'z' && upstr[i] >= 'a') { + upstr[i] -= 32; // 32 is the difference between lowercase and uppercase ASCII + } + } + + return upstr; +} +} +} +#endif diff --git a/utils/time_util.cpp b/utils/time_util.cpp new file mode 100755 index 0000000..e992447 --- /dev/null +++ b/utils/time_util.cpp @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "time_util.h" +#include +#include +#include +#include +#include +#include +#include "intell_voice_log.h" + +#define LOG_TAG "TimeUtil" + +using namespace std; +static const int INVALID_TIME_T = -1; + +namespace OHOS { +namespace IntellVoiceUtils { +AutoTimer::AutoTimer() +{ + Reset(); +} + +AutoTimer::AutoTimer(const std::string &logInfo) : mLogInfo(logInfo) +{ + Reset(); +} + +AutoTimer::~AutoTimer() +{ + if (mIsReset) { + PrintTimeElapse(); + } +} + +void AutoTimer::PrintTimeElapse() +{ + PrintTimeElapse(mLogInfo); +} + +void AutoTimer::PrintTimeElapse(const std::string &logInfo) +{ + std::string log; + + try { + if (!logInfo.empty()) { + log += logInfo + " "; + } else { + log += mLogInfo + " "; + } + + std::ostringstream ss; + ss << TimeElapseMs(); + log += "time elapse: " + ss.str() + "ms"; + } catch (const std::length_error& err) { + INTELL_VOICE_LOG_ERROR("length error"); + return; + } + + INTELL_VOICE_LOG_DEBUG("%s, %s", __FUNCTION__, log.c_str()); + + mIsReset = false; +} + +void AutoTimer::Reset() +{ + TimeUtil::GetTime(mTimeStart); + mIsReset = true; +} + +long AutoTimer::TimeElapseUs() +{ + mIsReset = false; + + timespec timeEnd; + TimeUtil::GetTime(timeEnd); + + return TimeUtil::TimeElapseUs(mTimeStart, timeEnd); +} + +uint32_t AutoTimer::TimeElapseMs() +{ + return TimeElapseUs() / MS_PER_US; +} + +uint32_t AutoTimer::TimeElapseS() +{ + return TimeElapseUs() / (S_PER_MS * MS_PER_US); +} + +string TimeUtil::GetCurrTime(TimeFormat format) +{ + time_t rawTime; + struct tm *timeInfo = nullptr; + char buffer[100] = { 0 }; + + time(&rawTime); + timeInfo = localtime(&rawTime); + if (timeInfo != nullptr) { + if (format == TIME_FORMAT_DEFAULT) { + strftime(buffer, sizeof(buffer), "%Y_%m_%d_%H_%M_%S_", timeInfo); + } else if (format == TIME_FORMAT_CONTINOUS) { + strftime(buffer, sizeof(buffer), "%Y%m%d%H%M%S", timeInfo); + } else if (format == TIME_FORMAT_STANDARD) { + strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", timeInfo); + } else { + INTELL_VOICE_LOG_WARN("invalid format:%d", format); + } + } + std::string str(buffer); + + return str; +} + +string TimeUtil::GetCurrTimeUs() +{ + struct timeval tv; + char buffer[100] = {0}; + if (gettimeofday(&tv, nullptr) == -1) { + INTELL_VOICE_LOG_ERROR("get time of day error"); + return ""; + } + struct tm *timeInfo = localtime(&tv.tv_sec); + if (timeInfo != nullptr) { + strftime(buffer, sizeof(buffer), "%Y%m%d%H%M%S", timeInfo); + } + string str(buffer); + stringstream ss; + ss << tv.tv_usec; + str += ss.str(); + return str; +} + +time_t TimeUtil::GetFormatTimeToSec(const string &formatTime) +{ + INTELL_VOICE_LOG_DEBUG("GetFormatTimeToSec, formatTime is %s", formatTime.c_str()); + struct tm s_tm; + + if (!strptime(formatTime.c_str(), "%Y%m%d%H%M%S", &s_tm)) { + INTELL_VOICE_LOG_ERROR("get file create time error"); + return INVALID_TIME_T; + } + + return mktime(&s_tm); +} + +bool TimeUtil::IsFormatTimeExpired(const string &formatTime, int maxKeepTime) +{ + time_t currentTime; + time_t originalTime; + + currentTime = time(nullptr); + originalTime = GetFormatTimeToSec(formatTime); + INTELL_VOICE_LOG_DEBUG("IsFormatTimeExpired, originalTime is %ld, currentTime is %ld, maxKeepTime is %d", + originalTime, currentTime, maxKeepTime); + + if ((originalTime == INVALID_TIME_T) || (currentTime == INVALID_TIME_T)) { + INTELL_VOICE_LOG_ERROR("get sys time error"); + return false; + } + + return (currentTime >= originalTime) && (currentTime - originalTime >= maxKeepTime); +} + +uint64_t TimeUtil::GetCurrentTimeMs() +{ + return static_cast(std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()).count()); +} +} +} diff --git a/utils/time_util.h b/utils/time_util.h new file mode 100755 index 0000000..94d4cd5 --- /dev/null +++ b/utils/time_util.h @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef TIME_UTIL_H +#define TIME_UTIL_H + +#include +#include +#include "base_constants.h" + +namespace OHOS { +namespace IntellVoiceUtils { +enum TimeFormat { + TIME_FORMAT_DEFAULT = 0, + TIME_FORMAT_CONTINOUS, + TIME_FORMAT_STANDARD, + TIME_FORMAT_NUM +}; + +class AutoTimer { +public: + AutoTimer(); + explicit AutoTimer(const std::string &logInfo); + virtual ~AutoTimer(); + + void PrintTimeElapse(); + void PrintTimeElapse(const std::string &logInfo); + void Reset(); + long TimeElapseUs(); + uint32_t TimeElapseMs(); + uint32_t TimeElapseS(); + +private: + + std::string mLogInfo; + timespec mTimeStart { 0, 0 }; + bool mIsReset { true }; +}; + +class TimeUtil { +public: + TimeUtil() {} + ~TimeUtil() {} + static std::string GetCurrTime(TimeFormat format = TIME_FORMAT_DEFAULT); + static std::string GetCurrTimeUs(); + static time_t GetFormatTimeToSec(const std::string &formatTime); + static bool IsFormatTimeExpired(const std::string &formatTime, int maxKeepTime); + static void GetTime(timespec &start); + static uint32_t TimeElapse(const timespec &start); + static void TimeElapse(const timespec &start, const timespec &end); + static long TimeElapseUs(const timespec &start, const timespec &end); + static uint64_t GetCurrentTimeMs(); +}; + +inline void TimeUtil::GetTime(timespec &start) +{ + if (clock_gettime(CLOCK_MONOTONIC, &start) == -1) { + return; + } +} + +inline uint32_t TimeUtil::TimeElapse(const timespec &start) +{ + timespec current; + if (clock_gettime(CLOCK_REALTIME, ¤t) == -1) { + return 0; + } + + return (current.tv_sec > start.tv_sec) ? (current.tv_sec - start.tv_sec) : 0; +} + +inline void TimeUtil::TimeElapse(const timespec &start, const timespec &end) +{ + long secs = end.tv_sec - start.tv_sec; + long hour = secs / (H_PER_MIN * MIN_PER_S); + long min = (secs % (H_PER_MIN * MIN_PER_S)) / MIN_PER_S; + long sec = secs % MIN_PER_S; + + std::cout << hour << ":" << min << ":" << sec << std::endl; + return; +} + +inline long TimeUtil::TimeElapseUs(const timespec &start, const timespec &end) +{ + long usecs = MS_PER_US * S_PER_MS * (end.tv_sec - start.tv_sec) + (end.tv_nsec - start.tv_nsec) / US_PER_NS; + return usecs; +} +} +} + +#endif