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 "intell_voice_engine_manager.h"
16
17 #include <vector>
18 #include <fstream>
19 #include <cstdio>
20 #include "audio_system_manager.h"
21 #include "idevmgr_hdi.h"
22 #include "intell_voice_log.h"
23 #include "intell_voice_util.h"
24 #include "engine_factory.h"
25 #include "wakeup_engine.h"
26 #include "iservice_registry.h"
27 #include "intell_voice_generic_factory.h"
28 #include "memory_guard.h"
29 #include "iproxy_broker.h"
30 #include "engine_host_manager.h"
31 #include "string_util.h"
32 #include "clone_update_strategy.h"
33 #include "silence_update_strategy.h"
34 #include "whisper_update_strategy.h"
35 #include "update_engine_utils.h"
36 #include "json/json.h"
37 #include "intell_voice_sensibility.h"
38 #include "headset_wakeup_wrapper.h"
39 #include "engine_callback_message.h"
40 #include "data_operation_callback.h"
41 #include "history_info_mgr.h"
42 #include "intell_voice_definitions.h"
43
44 #define LOG_TAG "IntellVoiceEngineManager"
45
46 using namespace OHOS::IntellVoiceUtils;
47 using namespace OHOS::HDI::IntelligentVoice::Engine::V1_0;
48 using OHOS::HDI::DeviceManager::V1_0::IDeviceManager;
49
50 namespace OHOS {
51 namespace IntellVoiceEngine {
52 static const std::string XIAOYIXIAOYI = "\xE5\xB0\x8F\xE8\x89\xBA\xE5\xB0\x8F\xE8\x89\xBA";
53 static const std::string LANGUAGE_TYPE_CHN = "zh";
54 std::atomic<bool> IntellVoiceEngineManager::screenoff_{false};
55 std::atomic<bool> IntellVoiceEngineManager::g_enrollResult[ENGINE_TYPE_BUT] = {false, false, false};
56
57 std::shared_ptr<IntellVoiceEngineManager> IntellVoiceEngineManager::instance_ = nullptr;
58 std::mutex IntellVoiceEngineManager::instanceMutex_;
59
IntellVoiceEngineManager()60 IntellVoiceEngineManager::IntellVoiceEngineManager()
61 {
62 }
63
~IntellVoiceEngineManager()64 IntellVoiceEngineManager::~IntellVoiceEngineManager()
65 {
66 }
67
CreateEngine(IntellVoiceEngineType type,const std::string & param,bool reEnroll)68 sptr<IIntellVoiceEngine> IntellVoiceEngineManager::CreateEngine(IntellVoiceEngineType type,
69 const std::string ¶m, bool reEnroll)
70 {
71 INTELL_VOICE_LOG_INFO("enter, type:%{public}d", type);
72 SetEnrollResult(type, false);
73 if (ApplyArbitration(type, engines_) != ARBITRATION_OK) {
74 INTELL_VOICE_LOG_ERROR("policy manager reject create engine, type:%{public}d", type);
75 return nullptr;
76 }
77
78 if (type != INTELL_VOICE_WAKEUP) {
79 auto engine = GetEngine(INTELL_VOICE_WAKEUP, engines_);
80 if (engine != nullptr) {
81 engine->ReleaseAdapter();
82 }
83 }
84
85 return CreateEngineInner(type, param, reEnroll);
86 }
87
CreateEngineInner(IntellVoiceEngineType type,const std::string & param,bool reEnroll)88 sptr<IIntellVoiceEngine> IntellVoiceEngineManager::CreateEngineInner(IntellVoiceEngineType type,
89 const std::string ¶m, bool reEnroll)
90 {
91 INTELL_VOICE_LOG_INFO("create engine enter, type: %{public}d", type);
92 OHOS::IntellVoiceUtils::MemoryGuard memoryGuard;
93 sptr<EngineBase> engine = GetEngine(type, engines_);
94 if (engine != nullptr) {
95 return engine;
96 }
97
98 engine = EngineFactory::CreateEngineInst(type, param, reEnroll);
99 if (engine == nullptr) {
100 INTELL_VOICE_LOG_ERROR("create engine failed, type:%{public}d", type);
101 return nullptr;
102 }
103 engines_[type] = engine;
104 INTELL_VOICE_LOG_INFO("create engine ok");
105 return engine;
106 }
107
ReleaseEngineInner(IntellVoiceEngineType type)108 int32_t IntellVoiceEngineManager::ReleaseEngineInner(IntellVoiceEngineType type)
109 {
110 OHOS::IntellVoiceUtils::MemoryGuard memoryGuard;
111 auto it = engines_.find(type);
112 if (it == engines_.end()) {
113 INTELL_VOICE_LOG_WARN("there is no engine(%{public}d) in list", type);
114 return 0;
115 }
116
117 if (it->second != nullptr) {
118 it->second->Detach();
119 it->second = nullptr;
120 }
121
122 engines_.erase(type);
123 return 0;
124 }
125
ClearUserDataInner()126 void IntellVoiceEngineManager::ClearUserDataInner()
127 {
128 UpdateEngineController::ForceRelease();
129 auto engine = GetEngine(INTELL_VOICE_WAKEUP, engines_);
130 if (engine != nullptr) {
131 engine->Detach();
132 }
133 auto wakeupPhrase = HistoryInfoMgr::GetInstance().GetStringKVPair(KEY_WAKEUP_PHRASE);
134 if (!wakeupPhrase.empty()) {
135 if (HistoryInfoMgr::GetInstance().GetStringKVPair(KEY_LANGUAGE)
136 == LANGUAGE_TYPE_CHN && wakeupPhrase != XIAOYIXIAOYI) {
137 wakeupPhrase = "Default";
138 }
139 EngineHostManager::GetInstance().ClearUserWakeupData(wakeupPhrase);
140 }
141 }
142
CreateOrResetWakeupEngine()143 bool IntellVoiceEngineManager::CreateOrResetWakeupEngine()
144 {
145 auto engine = GetEngine(INTELL_VOICE_WAKEUP, engines_);
146 if (engine != nullptr) {
147 INTELL_VOICE_LOG_INFO("wakeup engine is existed");
148 engine->ReleaseAdapter();
149 if (!engine->ResetAdapter()) {
150 INTELL_VOICE_LOG_ERROR("failed to reset adapter");
151 return false;
152 }
153 } else {
154 if (CreateEngineInner(INTELL_VOICE_WAKEUP) == nullptr) {
155 INTELL_VOICE_LOG_ERROR("failed to create wakeup engine");
156 return false;
157 }
158 }
159 return true;
160 }
161
ServiceStopProc()162 int32_t IntellVoiceEngineManager::ServiceStopProc()
163 {
164 sptr<EngineBase> wakeupEngine = GetEngine(INTELL_VOICE_WAKEUP, engines_);
165 if (wakeupEngine == nullptr) {
166 INTELL_VOICE_LOG_INFO("wakeup engine is not existed");
167 return -1;
168 }
169 wakeupEngine->Detach();
170 wakeupEngine->NotifyHeadsetHostEvent(HEADSET_HOST_OFF);
171 return 0;
172 }
173
RegisterProxyDeathRecipient(IntellVoiceEngineType type,const sptr<IRemoteObject> & object)174 bool IntellVoiceEngineManager::RegisterProxyDeathRecipient(IntellVoiceEngineType type,
175 const sptr<IRemoteObject> &object)
176 {
177 std::lock_guard<std::mutex> lock(deathMutex_);
178 INTELL_VOICE_LOG_INFO("enter, type:%{public}d", type);
179 deathRecipientObj_[type] = object;
180 if (type == INTELL_VOICE_ENROLL) {
181 proxyDeathRecipient_[type] = new (std::nothrow) IntellVoiceDeathRecipient([&]() {
182 INTELL_VOICE_LOG_INFO("receive enroll proxy death recipient, release enroll engine");
183 EngineCallbackMessage::CallFunc(HANDLE_RELEASE_ENGINE, INTELL_VOICE_ENROLL);
184 });
185 } else if (type == INTELL_VOICE_WAKEUP) {
186 proxyDeathRecipient_[type] = new (std::nothrow) IntellVoiceDeathRecipient([&]() {
187 INTELL_VOICE_LOG_INFO("receive wakeup proxy death recipient, clear wakeup engine callback");
188 EngineCallbackMessage::CallFunc(HANDLE_CLEAR_WAKEUP_ENGINE_CB);
189 });
190 } else if (type == INTELL_VOICE_HEADSET_WAKEUP) {
191 proxyDeathRecipient_[type] = new (std::nothrow) IntellVoiceDeathRecipient([&]() {
192 INTELL_VOICE_LOG_INFO("receive headset wakeup proxy death recipient, notify headset host off");
193 EngineCallbackMessage::CallFunc(HANDLE_HEADSET_HOST_DIE);
194 });
195 } else {
196 INTELL_VOICE_LOG_ERROR("invalid type:%{public}d", type);
197 return false;
198 }
199
200 if (proxyDeathRecipient_[type] == nullptr) {
201 INTELL_VOICE_LOG_ERROR("create death recipient failed");
202 return false;
203 }
204
205 return deathRecipientObj_[type]->AddDeathRecipient(proxyDeathRecipient_[type]);
206 }
207
DeregisterProxyDeathRecipient(IntellVoiceEngineType type)208 bool IntellVoiceEngineManager::DeregisterProxyDeathRecipient(IntellVoiceEngineType type)
209 {
210 std::lock_guard<std::mutex> lock(deathMutex_);
211 INTELL_VOICE_LOG_INFO("enter, type:%{public}d", type);
212 if (deathRecipientObj_.count(type) == 0 || deathRecipientObj_[type] == nullptr) {
213 INTELL_VOICE_LOG_ERROR("death obj is nullptr, type:%{public}d", type);
214 return false;
215 }
216 if (proxyDeathRecipient_.count(type) == 0 || proxyDeathRecipient_[type] == nullptr) {
217 INTELL_VOICE_LOG_ERROR("death recipient is nullptr, type:%{public}d", type);
218 deathRecipientObj_.erase(type);
219 return false;
220 }
221
222 auto ret = deathRecipientObj_[type]->RemoveDeathRecipient(proxyDeathRecipient_[type]);
223 deathRecipientObj_.erase(type);
224 proxyDeathRecipient_.erase(type);
225 return ret;
226 }
227
AnyEngineExist(const std::vector<IntellVoiceEngineType> & types)228 bool IntellVoiceEngineManager::AnyEngineExist(const std::vector<IntellVoiceEngineType> &types)
229 {
230 for (const auto &type : types) {
231 if (IsEngineExist(type)) {
232 return true;
233 }
234 }
235 return false;
236 }
237
IsEngineExist(IntellVoiceEngineType type)238 bool IntellVoiceEngineManager::IsEngineExist(IntellVoiceEngineType type)
239 {
240 sptr<EngineBase> engine = GetEngine(type, engines_);
241 if (engine != nullptr) {
242 INTELL_VOICE_LOG_INFO("engine exist, type:%{public}d", type);
243 return true;
244 }
245
246 if (type == INTELL_VOICE_UPDATE && GetUpdateState()) {
247 INTELL_VOICE_LOG_ERROR("update is running");
248 return true;
249 }
250
251 return false;
252 }
253
CreateUpdateEngine(const std::string & param,bool reEnroll)254 bool IntellVoiceEngineManager::CreateUpdateEngine(const std::string ¶m, bool reEnroll)
255 {
256 sptr<IIntellVoiceEngine> updateEngine = CreateEngine(INTELL_VOICE_UPDATE, param, reEnroll);
257 if (updateEngine == nullptr) {
258 INTELL_VOICE_LOG_ERROR("updateEngine is nullptr");
259 return false;
260 }
261
262 return true;
263 }
264
ReleaseUpdateEngine()265 void IntellVoiceEngineManager::ReleaseUpdateEngine()
266 {
267 EngineCallbackMessage::CallFunc(RELEASE_ENGINE, INTELL_VOICE_UPDATE);
268 }
269
GetUploadFiles(int numMax,std::vector<UploadFilesFromHdi> & files)270 int32_t IntellVoiceEngineManager::GetUploadFiles(int numMax, std::vector<UploadFilesFromHdi> &files)
271 {
272 std::vector<UploadHdiFile> hdiFiles;
273 auto ret = EngineHostManager::GetInstance().GetUploadFiles(numMax, hdiFiles);
274 if (ret != 0) {
275 INTELL_VOICE_LOG_INFO("failed to get upload file, ret:%{public}d", ret);
276 return ret;
277 }
278
279 for (auto item : hdiFiles) {
280 UploadFilesFromHdi file;
281 file.type = item.type;
282 file.filesDescription = item.filesDescription;
283 for (auto mem : item.filesContent) {
284 file.filesContent.emplace_back(mem);
285 }
286 file.type = item.type;
287 files.emplace_back(file);
288 }
289 return ret;
290 }
291
GetParameter(const std::string & key)292 std::string IntellVoiceEngineManager::GetParameter(const std::string &key)
293 {
294 std::string val = "";
295
296 if (key == "isEnrolled") {
297 HistoryInfoMgr &historyInfoMgr = HistoryInfoMgr::GetInstance();
298 val = historyInfoMgr.GetStringKVPair(KEY_WAKEUP_VESRION).empty() ? "false" : "true";
299 INTELL_VOICE_LOG_INFO("get is enroll result %{public}s", val.c_str());
300 } else if (key == "isNeedReEnroll") {
301 val = UpdateEngineUtils::IsVersionUpdate() ? "true" : "false";
302 INTELL_VOICE_LOG_INFO("get nedd reenroll result %{public}s", val.c_str());
303 } else if (key == "isWhispering") {
304 auto audioSystemManager = AudioStandard::AudioSystemManager::GetInstance();
305 if (audioSystemManager == nullptr) {
306 INTELL_VOICE_LOG_ERROR("audioSystemManager is nullptr");
307 return val;
308 }
309 val = std::to_string(audioSystemManager->IsWhispering());
310 INTELL_VOICE_LOG_INFO("get isWhispering result %{public}s", val.c_str());
311 }
312
313 return val;
314 }
315
SetParameter(const std::string & sensibility)316 int32_t IntellVoiceEngineManager::SetParameter(const std::string &sensibility)
317 {
318 auto engine = GetEngine(INTELL_VOICE_WAKEUP, engines_);
319 if (engine != nullptr) {
320 engine->SetParameter(SENSIBILITY_TEXT + sensibility);
321 }
322 return 0;
323 }
324
GetWakeupSourceFilesList(std::vector<std::string> & cloneFiles)325 int32_t IntellVoiceEngineManager::GetWakeupSourceFilesList(std::vector<std::string> &cloneFiles)
326 {
327 return EngineHostManager::GetInstance().GetWakeupSourceFilesList(cloneFiles);
328 }
329
GetWakeupSourceFile(const std::string & filePath,std::vector<uint8_t> & buffer)330 int32_t IntellVoiceEngineManager::GetWakeupSourceFile(const std::string &filePath, std::vector<uint8_t> &buffer)
331 {
332 return EngineHostManager::GetInstance().GetWakeupSourceFile(filePath, buffer);
333 }
334
SendWakeupFile(const std::string & filePath,const std::vector<uint8_t> & buffer)335 int32_t IntellVoiceEngineManager::SendWakeupFile(const std::string &filePath, const std::vector<uint8_t> &buffer)
336 {
337 if (buffer.data() == nullptr) {
338 INTELL_VOICE_LOG_ERROR("send update callback is nullptr");
339 }
340
341 return EngineHostManager::GetInstance().SendWakeupFile(filePath, buffer);
342 }
343
CloneUpdate(const std::string & wakeupInfo,const sptr<IRemoteObject> & object)344 int32_t IntellVoiceEngineManager::CloneUpdate(const std::string &wakeupInfo, const sptr<IRemoteObject> &object)
345 {
346 sptr<IIntelligentVoiceUpdateCallback> updateCallback = iface_cast<IIntelligentVoiceUpdateCallback>(object);
347 if (updateCallback == nullptr) {
348 INTELL_VOICE_LOG_ERROR("update callback is nullptr");
349 return -1;
350 }
351
352 if (wakeupInfo.empty()) {
353 INTELL_VOICE_LOG_ERROR("clone info empty");
354 return -1;
355 }
356
357 std::shared_ptr<CloneUpdateStrategy> cloneStrategy =
358 std::make_shared<CloneUpdateStrategy>(wakeupInfo, updateCallback);
359 if (cloneStrategy == nullptr) {
360 INTELL_VOICE_LOG_ERROR("clone strategy is nullptr");
361 return -1;
362 }
363
364 INTELL_VOICE_LOG_INFO("enter");
365 std::shared_ptr<IUpdateStrategy> strategy = std::dynamic_pointer_cast<IUpdateStrategy>(cloneStrategy);
366 return CreateUpdateEngineUntilTime(strategy);
367 }
368
SilenceUpdate()369 int32_t IntellVoiceEngineManager::SilenceUpdate()
370 {
371 std::shared_ptr<SilenceUpdateStrategy> silenceStrategy = std::make_shared<SilenceUpdateStrategy>("");
372 if (silenceStrategy == nullptr) {
373 INTELL_VOICE_LOG_ERROR("silence strategy is nullptr");
374 return -1;
375 }
376
377 INTELL_VOICE_LOG_INFO("enter");
378 std::shared_ptr<IUpdateStrategy> strategy = std::dynamic_pointer_cast<IUpdateStrategy>(silenceStrategy);
379 return CreateUpdateEngineUntilTime(strategy);
380 }
381
WhisperVprUpdate(bool reEnroll)382 int32_t IntellVoiceEngineManager::WhisperVprUpdate(bool reEnroll)
383 {
384 INTELL_VOICE_LOG_INFO("enter");
385 std::shared_ptr<IUpdateStrategy> strategy = std::make_shared<WhisperUpdateStrategy>("WhisperVprUpdate");
386 if (strategy == nullptr) {
387 INTELL_VOICE_LOG_ERROR("strategy is nullptr");
388 return -1;
389 }
390
391 return CreateUpdateEngineUntilTime(strategy, reEnroll);
392 }
393
394
GetDspSensibility(const std::string & sensibility,const std::string & dspFeature,const std::string & configPath)395 std::string IntellVoiceEngineManager::GetDspSensibility(const std::string &sensibility,
396 const std::string &dspFeature, const std::string &configPath)
397 {
398 return IntellVoiceSensibility::GetDspSensibility(sensibility, dspFeature, configPath);
399 }
400
HeadsetHostDie()401 void IntellVoiceEngineManager::HeadsetHostDie()
402 {
403 auto engine = GetEngine(INTELL_VOICE_WAKEUP, engines_);
404 if (engine != nullptr) {
405 engine->NotifyHeadsetHostEvent(HEADSET_HOST_OFF);
406 }
407 }
408
IsNeedUpdateComplete(int32_t result,const std::string & param)409 bool IntellVoiceEngineManager::IsNeedUpdateComplete(int32_t result, const std::string ¶m)
410 {
411 bool isLast = false;
412 UpdateEngineController::UpdateCompleteProc(static_cast<UpdateState>(result), param, isLast);
413 if ((IsEngineExist(INTELL_VOICE_ENROLL)) || (!isLast)) {
414 INTELL_VOICE_LOG_INFO("enroll engine is existed, or is not last:%{public}d", isLast);
415 return false;
416 }
417 return true;
418 }
419
IsNeedUpdateRetry()420 bool IntellVoiceEngineManager::IsNeedUpdateRetry()
421 {
422 if (UpdateEngineController::UpdateRetryProc()) {
423 INTELL_VOICE_LOG_INFO("retry to update or already force to stop");
424 return false;
425 }
426 if (IsEngineExist(INTELL_VOICE_ENROLL)) {
427 INTELL_VOICE_LOG_INFO("enroll engine is existed, do nothing");
428 return false;
429 }
430 return true;
431 }
432
EngineOnDetected(int32_t uuid)433 void IntellVoiceEngineManager::EngineOnDetected(int32_t uuid)
434 {
435 auto engine = GetEngine(INTELL_VOICE_WAKEUP, engines_);
436 engine->OnDetected(uuid);
437 }
438
ClearWakeupEngineCb()439 void IntellVoiceEngineManager::ClearWakeupEngineCb()
440 {
441 sptr<EngineBase> engine = GetEngine(INTELL_VOICE_WAKEUP, engines_);
442 if (engine != nullptr) {
443 INTELL_VOICE_LOG_INFO("clear wakeup engine callback");
444 engine->SetCallback(nullptr);
445 }
446 }
447
GetScreenOff()448 bool IntellVoiceEngineManager::GetScreenOff()
449 {
450 return screenoff_.load();
451 }
452
SetScreenOff(bool value)453 void IntellVoiceEngineManager::SetScreenOff(bool value)
454 {
455 screenoff_.store(value);
456 }
457
SetDspSensibility(const std::string & sensibility)458 void IntellVoiceEngineManager::SetDspSensibility(const std::string &sensibility)
459 {
460 auto ret = EngineCallbackMessage::CallFunc(TRIGGERMGR_GET_PARAMETER, KEY_GET_WAKEUP_FEATURE);
461 std::string features = "";
462 if (ret.has_value()) {
463 try {
464 features = std::any_cast<std::string>(*ret);
465 } catch (const std::bad_any_cast&) {
466 INTELL_VOICE_LOG_ERROR("msg bus bad any cast");
467 return;
468 }
469 } else {
470 INTELL_VOICE_LOG_ERROR("msg bus return no value");
471 return;
472 }
473 auto value = GetDspSensibility(sensibility, features, WAKEUP_CONFIG_PATH);
474 if (value.empty()) {
475 INTELL_VOICE_LOG_ERROR("no sensibility value");
476 return;
477 }
478 EngineCallbackMessage::CallFunc(TRIGGERMGR_SET_PARAMETER, "WAKEUP_SENSIBILITY", value);
479 }
480
OnServiceStart()481 void IntellVoiceEngineManager::OnServiceStart()
482 {
483 LoadIntellVoiceHost();
484 }
485
OnServiceStop()486 void IntellVoiceEngineManager::OnServiceStop()
487 {
488 UnloadIntellVoiceHost();
489 }
490
LoadIntellVoiceHost()491 void IntellVoiceEngineManager::LoadIntellVoiceHost()
492 {
493 auto devmgr = IDeviceManager::Get();
494 if (devmgr == nullptr) {
495 INTELL_VOICE_LOG_ERROR("Get devmgr failed");
496 return;
497 }
498 INTELL_VOICE_LOG_INFO("Get devmgr success");
499 devmgr->UnloadDevice("intell_voice_engine_manager_service");
500 devmgr->LoadDevice("intell_voice_engine_manager_service");
501
502 if (!EngineHostManager::GetInstance().Init()) {
503 INTELL_VOICE_LOG_ERROR("init engine host failed");
504 return;
505 }
506
507 EngineHostManager::GetInstance().RegisterEngineHDIDeathRecipient();
508 EngineHostManager::GetInstance().SetDataOprCallback();
509 }
510
UnloadIntellVoiceHost()511 void IntellVoiceEngineManager::UnloadIntellVoiceHost()
512 {
513 auto devmgr = IDeviceManager::Get();
514 if (devmgr != nullptr) {
515 INTELL_VOICE_LOG_INFO("Get devmgr success");
516 EngineHostManager::GetInstance().DeregisterEngineHDIDeathRecipient();
517 devmgr->UnloadDevice("intell_voice_engine_manager_service");
518 } else {
519 INTELL_VOICE_LOG_ERROR("Get devmgr failed");
520 }
521 }
522 } // namespace IntellVoiceEngine
523 } // namespace OHOS
524