1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "engine_util.h"
16 #include <ashmem.h>
17 
18 #include "intell_voice_log.h"
19 #include "string_util.h"
20 #include "scope_guard.h"
21 #include "engine_host_manager.h"
22 #include "trigger_manager.h"
23 #include "intell_voice_service_manager.h"
24 
25 #define LOG_TAG "EngineUtils"
26 
27 using namespace OHOS::IntellVoiceUtils;
28 using namespace OHOS::HDI::IntelligentVoice::Engine::V1_0;
29 using namespace OHOS::IntellVoiceTrigger;
30 
31 namespace OHOS {
32 namespace IntellVoiceEngine {
33 static const std::string KEY_GET_WAKEUP_FEATURE = "wakeup_features";
34 static const std::string LANGUAGE_TEXT = "language=";
35 static const std::string AREA_TEXT = "area=";
36 static const std::string SENSIBILITY_TEXT = "sensibility=";
37 
EngineUtil()38 EngineUtil::EngineUtil()
39 {
40     desc_.adapterType = ADAPTER_TYPE_BUT;
41 }
42 
SetParameter(const std::string & keyValueList)43 int32_t EngineUtil::SetParameter(const std::string &keyValueList)
44 {
45     if (adapter_ == nullptr) {
46         INTELL_VOICE_LOG_ERROR("adapter is nullptr");
47         return -1;
48     }
49     return adapter_->SetParameter(keyValueList);
50 }
51 
GetParameter(const std::string & key)52 std::string EngineUtil::GetParameter(const std::string &key)
53 {
54     if (adapter_ == nullptr) {
55         INTELL_VOICE_LOG_ERROR("adapter is nullptr");
56         return "";
57     }
58 
59     std::string value;
60     adapter_->GetParameter(key, value);
61     return value;
62 }
63 
WriteAudio(const uint8_t * buffer,uint32_t size)64 int32_t EngineUtil::WriteAudio(const uint8_t *buffer, uint32_t size)
65 {
66     if (adapter_ == nullptr) {
67         INTELL_VOICE_LOG_ERROR("adapter is nullptr");
68         return -1;
69     }
70 
71     if (buffer == nullptr || size == 0) {
72         INTELL_VOICE_LOG_ERROR("buffer is invalid, size:%{public}u", size);
73         return -1;
74     }
75 
76     std::vector<uint8_t> audioBuff(&buffer[0], &buffer[size]);
77     return adapter_->WriteAudio(audioBuff);
78 }
79 
Stop()80 int32_t EngineUtil::Stop()
81 {
82     if (adapter_ == nullptr) {
83         INTELL_VOICE_LOG_ERROR("adapter is nullptr");
84         return -1;
85     }
86     return adapter_->Stop();
87 }
88 
GetWakeupPcm(std::vector<uint8_t> & data)89 int32_t EngineUtil::GetWakeupPcm(std::vector<uint8_t> &data)
90 {
91     if (adapter_ == nullptr) {
92         INTELL_VOICE_LOG_ERROR("adapter is nullptr");
93         return -1;
94     }
95     return adapter_->GetWakeupPcm(data);
96 }
97 
Evaluate(const std::string & word,EvaluationResultInfo & info)98 int32_t EngineUtil::Evaluate(const std::string &word, EvaluationResultInfo &info)
99 {
100     if (adapter_ == nullptr) {
101         INTELL_VOICE_LOG_ERROR("adapter is nullptr");
102         return -1;
103     }
104 
105     return adapter_->Evaluate(word, info);
106 }
107 
SetDspFeatures()108 bool EngineUtil::SetDspFeatures()
109 {
110     if (adapter_ == nullptr) {
111         INTELL_VOICE_LOG_ERROR("adapter is nullptr");
112         return false;
113     }
114 
115     auto triggerMgr = TriggerManager::GetInstance();
116     if (triggerMgr == nullptr) {
117         INTELL_VOICE_LOG_ERROR("trigger manager is nullptr");
118         return false;
119     }
120 
121     std::string features = triggerMgr->GetParameter(KEY_GET_WAKEUP_FEATURE);
122     if (features == "") {
123         INTELL_VOICE_LOG_WARN("failed to get wakeup dsp feature");
124         features = HistoryInfoMgr::GetInstance().GetWakeupDspFeature();
125         if (features == "") {
126             INTELL_VOICE_LOG_WARN("no historical wakeup dsp feature");
127             return false;
128         }
129     } else {
130         HistoryInfoMgr::GetInstance().SetWakeupDspFeature(features);
131     }
132 
133     std::string kvPair = KEY_GET_WAKEUP_FEATURE + "=" + features;
134     adapter_->SetParameter(kvPair);
135     return true;
136 }
137 
WriteBufferFromAshmem(uint8_t * & buffer,uint32_t size,sptr<OHOS::Ashmem> ashmem)138 void EngineUtil::WriteBufferFromAshmem(uint8_t *&buffer, uint32_t size, sptr<OHOS::Ashmem> ashmem)
139 {
140     if (!ashmem->MapReadOnlyAshmem()) {
141         INTELL_VOICE_LOG_ERROR("map ashmem failed");
142         return;
143     }
144 
145     const uint8_t *tmpBuffer = static_cast<const uint8_t *>(ashmem->ReadFromAshmem(size, 0));
146     if (tmpBuffer == nullptr) {
147         INTELL_VOICE_LOG_ERROR("read from ashmem failed");
148         return;
149     }
150 
151     buffer = new (std::nothrow) uint8_t[size];
152     if (buffer == nullptr) {
153         INTELL_VOICE_LOG_ERROR("allocate buffer failed");
154         return;
155     }
156 
157     if (memcpy_s(buffer, size, tmpBuffer, size) != 0) {
158         INTELL_VOICE_LOG_ERROR("memcpy_s failed");
159         return;
160     }
161 }
162 
ProcDspModel(OHOS::HDI::IntelligentVoice::Engine::V1_0::ContentType type)163 void EngineUtil::ProcDspModel(OHOS::HDI::IntelligentVoice::Engine::V1_0::ContentType type)
164 {
165     INTELL_VOICE_LOG_INFO("enter");
166     uint8_t *buffer = nullptr;
167     uint32_t size = 0;
168     sptr<Ashmem> ashmem;
169     adapter_->Read(type, ashmem);
170     if (ashmem == nullptr) {
171         INTELL_VOICE_LOG_ERROR("ashmem is nullptr");
172         return;
173     }
174 
175     ON_SCOPE_EXIT_WITH_NAME(ashmemExit)
176     {
177         INTELL_VOICE_LOG_DEBUG("close ashmem");
178         ashmem->UnmapAshmem();
179         ashmem->CloseAshmem();
180     };
181 
182     size = static_cast<uint32_t>(ashmem->GetAshmemSize());
183     if (size == 0) {
184         INTELL_VOICE_LOG_ERROR("size is zero");
185         return;
186     }
187 
188     WriteBufferFromAshmem(buffer, size, ashmem);
189     if (buffer == nullptr) {
190         INTELL_VOICE_LOG_ERROR("buffer is nullptr");
191         return;
192     }
193 
194     ON_SCOPE_EXIT_WITH_NAME(bufferExit)
195     {
196         INTELL_VOICE_LOG_DEBUG("now delete buffer");
197         delete[] buffer;
198         buffer = nullptr;
199     };
200 
201     std::shared_ptr<GenericTriggerModel> model = std::make_shared<GenericTriggerModel>(VOICE_WAKEUP_MODEL_UUID,
202         TriggerModel::TriggerModelVersion::MODLE_VERSION_2, TriggerModel::TriggerModelType::VOICE_WAKEUP_TYPE);
203     if (model == nullptr) {
204         INTELL_VOICE_LOG_ERROR("model is null");
205         return;
206     }
207     model->SetData(buffer, size);
208     auto triggerMgr = TriggerManager::GetInstance();
209     if (triggerMgr == nullptr) {
210         INTELL_VOICE_LOG_ERROR("trigger manager is nullptr");
211         return;
212     }
213     triggerMgr->UpdateModel(model);
214 }
215 
SetLanguage()216 void EngineUtil::SetLanguage()
217 {
218     if (adapter_ == nullptr) {
219         INTELL_VOICE_LOG_ERROR("adapter is nullptr");
220         return;
221     }
222 
223     std::string language = HistoryInfoMgr::GetInstance().GetLanguage();
224     if (language.empty()) {
225         INTELL_VOICE_LOG_WARN("language is empty");
226         return;
227     }
228     adapter_->SetParameter(LANGUAGE_TEXT + language);
229 }
230 
SetArea()231 void EngineUtil::SetArea()
232 {
233     if (adapter_ == nullptr) {
234         INTELL_VOICE_LOG_ERROR("adapter is nullptr");
235         return;
236     }
237 
238     std::string area = HistoryInfoMgr::GetInstance().GetArea();
239     if (area.empty()) {
240         INTELL_VOICE_LOG_WARN("area is empty");
241         return;
242     }
243 
244     adapter_->SetParameter(AREA_TEXT + area);
245 }
246 
SetSensibility()247 void EngineUtil::SetSensibility()
248 {
249     if (adapter_ == nullptr) {
250         INTELL_VOICE_LOG_ERROR("adapter is nullptr");
251         return;
252     }
253 
254     std::string sensibility = HistoryInfoMgr::GetInstance().GetSensibility();
255     if (sensibility.empty()) {
256         INTELL_VOICE_LOG_WARN("sensibility is empty");
257         return;
258     }
259 
260     auto &mgr = IntellVoiceServiceManager::GetInstance();
261     if (mgr != nullptr) {
262         mgr->SetDspSensibility(sensibility);
263     }
264 
265     adapter_->SetParameter(SENSIBILITY_TEXT + sensibility);
266 }
267 }
268 }
269