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 "wakeup_engine_impl.h"
16
17 #include "audio_asr.h"
18 #include "audio_system_manager.h"
19 #include "audio_policy_manager.h"
20 #include "ipc_skeleton.h"
21 #include "v1_2/intell_voice_engine_types.h"
22 #include "adapter_callback_service.h"
23 #include "intell_voice_info.h"
24 #include "intell_voice_log.h"
25 #include "history_info_mgr.h"
26 #include "intell_voice_util.h"
27 #include "string_util.h"
28 #include "intell_voice_engine_manager.h"
29 #include "engine_callback_message.h"
30 #include "engine_host_manager.h"
31 #include "swing_service_wrapper.h"
32
33 #define LOG_TAG "WakeupEngineImpl"
34
35 using namespace OHOS::IntellVoice;
36 using namespace OHOS::AudioStandard;
37 using namespace OHOS::HDI::IntelligentVoice::Engine::V1_0;
38 using namespace OHOS::IntellVoiceUtils;
39
40 namespace OHOS {
41 namespace IntellVoiceEngine {
42 static constexpr uint32_t MIN_BUFFER_SIZE = 640;
43 static constexpr uint32_t INTERVAL = 100;
44 static constexpr int32_t CHANNEL_CNT = 1;
45 static constexpr int32_t BITS_PER_SAMPLE = 16;
46 static constexpr int32_t SAMPLE_RATE = 16000;
47 static const std::string WAKEUP_SOURCE_CHANNEL = "wakeup_source_channel";
48 static const std::string IS_CALLBACK_EXIST = "is_callback_exist";
49 static constexpr std::string_view DEFAULT_WAKEUP_PHRASE = "\xE5\xB0\x8F\xE8\x89\xBA\xE5\xB0\x8F\xE8\x89\xBA";
50 static constexpr int64_t RECOGNIZING_TIMEOUT_US = 10 * 1000 * 1000; //10s
51 static constexpr int64_t RECOGNIZE_COMPLETE_TIMEOUT_US = 2 * 1000 * 1000; //2s
52 static constexpr int64_t READ_CAPTURER_TIMEOUT_US = 10 * 1000 * 1000; //10s
53 static constexpr uint32_t MAX_WAKEUP_TASK_NUM = 200;
54 static const std::string WAKEUP_THREAD_NAME = "WakeupEngThread";
55 static const std::string WAKEUP_CONFORMER_EVENT_TYPE = "AUDIO_WAKEUP_1_5";
56 static const std::string WAKEUP_CONFORMER_DOMAIN_ID = "7";
57
WakeupEngineImpl()58 WakeupEngineImpl::WakeupEngineImpl() : ModuleStates(State(IDLE), "WakeupEngineImpl", "WakeupThread"),
59 TaskExecutor(WAKEUP_THREAD_NAME, MAX_WAKEUP_TASK_NUM)
60 {
61 InitStates();
62 capturerOptions_.streamInfo.samplingRate = AudioSamplingRate::SAMPLE_RATE_16000;
63 capturerOptions_.streamInfo.encoding = AudioEncodingType::ENCODING_PCM;
64 capturerOptions_.streamInfo.format = AudioSampleFormat::SAMPLE_S16LE;
65 capturerOptions_.streamInfo.channels = AudioChannel::MONO;
66 capturerOptions_.capturerInfo.sourceType = SourceType::SOURCE_TYPE_WAKEUP;
67 capturerOptions_.capturerInfo.capturerFlags = 0;
68 adapterListener_ = std::make_shared<WakeupAdapterListener>(
69 std::bind(&WakeupEngineImpl::OnWakeupEvent, this, std::placeholders::_1));
70 if (adapterListener_ == nullptr) {
71 INTELL_VOICE_LOG_ERROR("adapterListener_ is nullptr");
72 }
73 TaskExecutor::StartThread();
74 }
75
~WakeupEngineImpl()76 WakeupEngineImpl::~WakeupEngineImpl()
77 {
78 }
79
InitStates()80 bool WakeupEngineImpl::InitStates()
81 {
82 for (int i = IDLE; i <= READ_CAPTURER; i++) {
83 ForState(State(i))
84 .ACT(SET_LISTENER, HandleSetListener)
85 .ACT(SET_PARAM, HandleSetParam)
86 .ACT(GET_PARAM, HandleGetParam);
87 }
88
89 ForState(IDLE)
90 .ACT(INIT, HandleInit)
91 .ACT(RESET_ADAPTER, HandleResetAdapter);
92
93 ForState(INITIALIZING)
94 .ACT(INIT_DONE, HandleInitDone);
95
96 ForState(INITIALIZED)
97 .ACT(START_RECOGNIZE, HandleStart);
98
99 ForState(RECOGNIZING)
100 .WaitUntil(RECOGNIZING_TIMEOUT,
101 std::bind(&WakeupEngineImpl::HandleRecognizingTimeout, this, std::placeholders::_1, std::placeholders::_2),
102 RECOGNIZING_TIMEOUT_US)
103 .ACT(STOP_RECOGNIZE, HandleStop)
104 .ACT(RECOGNIZE_COMPLETE, HandleRecognizeComplete);
105
106 ForState(RECOGNIZED)
107 .WaitUntil(RECOGNIZE_COMPLETE_TIMEOUT,
108 std::bind(&WakeupEngineImpl::HandleStopCapturer, this, std::placeholders::_1, std::placeholders::_2),
109 RECOGNIZE_COMPLETE_TIMEOUT_US)
110 .ACT(GET_WAKEUP_PCM, HandleGetWakeupPcm)
111 .ACT(START_CAPTURER, HandleStartCapturer);
112
113 ForState(READ_CAPTURER)
114 .WaitUntil(READ_CAPTURER_TIMEOUT,
115 std::bind(&WakeupEngineImpl::HandleStopCapturer, this, std::placeholders::_1, std::placeholders::_2),
116 READ_CAPTURER_TIMEOUT_US)
117 .ACT(READ, HandleRead)
118 .ACT(STOP_CAPTURER, HandleStopCapturer);
119
120 FromState(INITIALIZING, READ_CAPTURER)
121 .ACT(RELEASE_ADAPTER, HandleRelease)
122 .ACT(RELEASE, HandleRelease);
123
124 return IsStatesInitSucc();
125 }
126
Handle(const StateMsg & msg)127 int32_t WakeupEngineImpl::Handle(const StateMsg &msg)
128 {
129 if (!IsStatesInitSucc()) {
130 INTELL_VOICE_LOG_ERROR("failed to init state");
131 return -1;
132 }
133
134 return ModuleStates::HandleMsg(msg);
135 }
136
GetWakeupSourceChannel()137 OHOS::AudioStandard::AudioChannel WakeupEngineImpl::GetWakeupSourceChannel()
138 {
139 auto ret = EngineCallbackMessage::CallFunc(TRIGGERMGR_GET_PARAMETER, WAKEUP_SOURCE_CHANNEL);
140 std::string channel = "";
141 if (ret.has_value()) {
142 try {
143 channel = std::any_cast<std::string>(*ret);
144 } catch (const std::bad_any_cast&) {
145 INTELL_VOICE_LOG_ERROR("msg bus bad any cast");
146 return AudioChannel::MONO;
147 }
148 } else {
149 INTELL_VOICE_LOG_ERROR("msg bus return no value");
150 return AudioChannel::MONO;
151 }
152
153 if (channel == "") {
154 INTELL_VOICE_LOG_INFO("no channle info");
155 return AudioChannel::MONO;
156 }
157
158 int32_t channelCnt = 0;
159 if (!StringUtil::StringToInt(channel, channelCnt)) {
160 INTELL_VOICE_LOG_ERROR("failed to get channel cnt");
161 return AudioChannel::MONO;
162 }
163
164 if ((channelCnt < AudioChannel::MONO) || (channelCnt > AudioChannel::CHANNEL_4)) {
165 INTELL_VOICE_LOG_INFO("invalid channel cnt:%{public}d", channelCnt);
166 return AudioChannel::MONO;
167 }
168
169 INTELL_VOICE_LOG_INFO("channel cnt:%{public}d", static_cast<int32_t>(channelCnt));
170 return static_cast<OHOS::AudioStandard::AudioChannel>(channelCnt);
171 }
172
SetCallbackInner()173 bool WakeupEngineImpl::SetCallbackInner()
174 {
175 INTELL_VOICE_LOG_INFO("enter");
176 if (adapter_ == nullptr) {
177 INTELL_VOICE_LOG_ERROR("adapter is nullptr");
178 return false;
179 }
180
181 if (adapterListener_ == nullptr) {
182 INTELL_VOICE_LOG_ERROR("adapter listener is nullptr");
183 return false;
184 }
185
186 callback_ = sptr<IIntellVoiceEngineCallback>(new (std::nothrow) AdapterCallbackService(adapterListener_));
187 if (callback_ == nullptr) {
188 INTELL_VOICE_LOG_ERROR("callback_ is nullptr");
189 return false;
190 }
191
192 adapter_->SetCallback(callback_);
193 return true;
194 }
195
AttachInner(const IntellVoiceEngineInfo & info)196 int32_t WakeupEngineImpl::AttachInner(const IntellVoiceEngineInfo &info)
197 {
198 INTELL_VOICE_LOG_INFO("enter");
199 if (adapter_ == nullptr) {
200 INTELL_VOICE_LOG_ERROR("adapter is nullptr");
201 return -1;
202 }
203
204 isPcmFromExternal_ = info.isPcmFromExternal;
205
206 IntellVoiceEngineAdapterInfo adapterInfo = {
207 .wakeupPhrase = info.wakeupPhrase,
208 .minBufSize = info.minBufSize,
209 .sampleChannels = info.sampleChannels,
210 .bitsPerSample = info.bitsPerSample,
211 .sampleRate = info.sampleRate,
212 };
213 return adapter_->Attach(adapterInfo);
214 }
215
SetParamOnAudioStart(int32_t uuid)216 void WakeupEngineImpl::SetParamOnAudioStart(int32_t uuid)
217 {
218 INTELL_VOICE_LOG_INFO("enter");
219 auto audioSystemManager = AudioSystemManager::GetInstance();
220 if (audioSystemManager == nullptr) {
221 INTELL_VOICE_LOG_ERROR("audioSystemManager is nullptr");
222 return;
223 }
224
225 #ifdef SUPPORT_WINDOW_MANAGER
226 SetFoldStatus();
227 #endif
228
229 audioSystemManager->SetAsrAecMode(AsrAecMode::STANDARD);
230 if (uuid == PROXIMAL_WAKEUP_MODEL_UUID) {
231 audioSystemManager->SetAsrNoiseSuppressionMode(AsrNoiseSuppressionMode::NEAR_FIELD);
232 } else {
233 audioSystemManager->SetAsrNoiseSuppressionMode(AsrNoiseSuppressionMode::STANDARD);
234 }
235 }
236
SetParamOnAudioStop()237 void WakeupEngineImpl::SetParamOnAudioStop()
238 {
239 INTELL_VOICE_LOG_INFO("enter");
240 auto audioSystemManager = AudioSystemManager::GetInstance();
241 if (audioSystemManager == nullptr) {
242 INTELL_VOICE_LOG_ERROR("audioSystemManager is nullptr");
243 return;
244 }
245 auto audioStreamManager = AudioStreamManager::GetInstance();
246 if (audioStreamManager == nullptr) {
247 INTELL_VOICE_LOG_ERROR("audioStreamManager is nullptr");
248 return;
249 }
250 std::vector<std::shared_ptr<AudioCapturerChangeInfo>> audioCapturerChangeInfos;
251 int32_t ret = audioStreamManager->GetCurrentCapturerChangeInfos(audioCapturerChangeInfos);
252 if (ret != 0) {
253 INTELL_VOICE_LOG_ERROR("GetCurrentCapturerChangeInfos failed");
254 }
255 for (auto it = audioCapturerChangeInfos.begin(); it != audioCapturerChangeInfos.end(); it++) {
256 if ((*it) == nullptr) {
257 INTELL_VOICE_LOG_ERROR("AudioCapturerChangeInfo ptr is nullptr");
258 continue;
259 }
260 if ((*it)->capturerInfo.sourceType == SOURCE_TYPE_VOICE_RECOGNITION) {
261 INTELL_VOICE_LOG_INFO("SOURCE_TYPE_VOICE_RECOGNITION exists");
262 return;
263 }
264 }
265 audioSystemManager->SetAsrAecMode(AsrAecMode::BYPASS);
266 audioSystemManager->SetAsrNoiseSuppressionMode(AsrNoiseSuppressionMode::BYPASS);
267 }
268
CreateWakeupSourceStopCallback()269 bool WakeupEngineImpl::CreateWakeupSourceStopCallback()
270 {
271 if (wakeupSourceStopCallback_ != nullptr) {
272 INTELL_VOICE_LOG_INFO("wakeup close cb is already created");
273 return true;
274 }
275
276 auto audioSystemManager = AudioSystemManager::GetInstance();
277 if (audioSystemManager == nullptr) {
278 INTELL_VOICE_LOG_ERROR("audioSystemManager is nullptr");
279 return false;
280 }
281
282 wakeupSourceStopCallback_ = std::make_shared<WakeupSourceStopCallback>();
283 if (wakeupSourceStopCallback_ == nullptr) {
284 INTELL_VOICE_LOG_ERROR("wakeup source stop callback is nullptr");
285 return false;
286 }
287
288 audioSystemManager->SetWakeUpSourceCloseCallback(wakeupSourceStopCallback_);
289 return true;
290 }
291
DestroyWakeupSourceStopCallback()292 void WakeupEngineImpl::DestroyWakeupSourceStopCallback()
293 {
294 if (wakeupSourceStopCallback_ == nullptr) {
295 INTELL_VOICE_LOG_INFO("wakeup close cb is already destroyed");
296 return;
297 }
298
299 auto audioSystemManager = AudioSystemManager::GetInstance();
300 if (audioSystemManager == nullptr) {
301 INTELL_VOICE_LOG_ERROR("audioSystemManager is nullptr");
302 return;
303 }
304
305 audioSystemManager->SetWakeUpSourceCloseCallback(nullptr);
306 wakeupSourceStopCallback_ = nullptr;
307 }
308
StartAudioSource()309 bool WakeupEngineImpl::StartAudioSource()
310 {
311 capturerOptions_.streamInfo.channels = GetWakeupSourceChannel();
312 auto listener = std::make_unique<AudioSourceListener>(
313 [&](uint8_t *buffer, uint32_t size, bool isEnd) {
314 ReadBufferCallback(buffer, size, isEnd);
315 },
316 [&]() {
317 INTELL_VOICE_LOG_INFO("end of pcm");
318 if (adapter_ != nullptr) {
319 adapter_->SetParameter("end_of_pcm=true");
320 }
321 });
322 if (listener == nullptr) {
323 INTELL_VOICE_LOG_ERROR("create listener failed");
324 return false;
325 }
326
327 WakeupSourceProcess::Init(capturerOptions_.streamInfo.channels);
328
329 audioSource_ = std::make_unique<AudioSource>(MIN_BUFFER_SIZE * static_cast<uint32_t>(
330 capturerOptions_.streamInfo.channels), INTERVAL, std::move(listener), capturerOptions_);
331 if (audioSource_ == nullptr) {
332 INTELL_VOICE_LOG_ERROR("create audio source failed");
333 WakeupSourceProcess::Release();
334 return false;
335 }
336
337 if (!audioSource_->Start()) {
338 INTELL_VOICE_LOG_ERROR("start capturer failed");
339 audioSource_ = nullptr;
340 WakeupSourceProcess::Release();
341 return false;
342 }
343
344 return true;
345 }
346
StopAudioSource()347 void WakeupEngineImpl::StopAudioSource()
348 {
349 INTELL_VOICE_LOG_INFO("enter");
350 if (audioSource_ == nullptr) {
351 INTELL_VOICE_LOG_INFO("audio source is nullptr, no need to stop");
352 return;
353 }
354 SetParamOnAudioStop();
355 audioSource_->Stop();
356 audioSource_ = nullptr;
357 WakeupSourceProcess::Release();
358 }
359
OnWakeupEvent(const OHOS::HDI::IntelligentVoice::Engine::V1_0::IntellVoiceEngineCallBackEvent & event)360 void WakeupEngineImpl::OnWakeupEvent(
361 const OHOS::HDI::IntelligentVoice::Engine::V1_0::IntellVoiceEngineCallBackEvent &event)
362 {
363 if (event.msgId == INTELL_VOICE_ENGINE_MSG_INIT_DONE) {
364 TaskExecutor::AddAsyncTask([this, result = event.result]() { OnInitDone(result); },
365 "WakeupEngineImpl::InitDone", false);
366 } else if (event.msgId == INTELL_VOICE_ENGINE_MSG_RECOGNIZE_COMPLETE) {
367 TaskExecutor::AddAsyncTask([this, result = event.result, info = event.info]() {
368 OnWakeupRecognition(result, info);
369 }, "WakeupEngineImpl::RecognizeComplete", false);
370 } else {
371 INTELL_VOICE_LOG_WARN("invalid msg id:%{public}d", event.msgId);
372 }
373 }
374
OnInitDone(int32_t result)375 void WakeupEngineImpl::OnInitDone(int32_t result)
376 {
377 INTELL_VOICE_LOG_INFO("on Init Done, result:%{public}d", result);
378 StateMsg msg(INIT_DONE, &result, sizeof(int32_t));
379 Handle(msg);
380 }
381
OnWakeupRecognition(int32_t result,const std::string & info)382 void WakeupEngineImpl::OnWakeupRecognition(int32_t result, const std::string &info)
383 {
384 INTELL_VOICE_LOG_INFO("on wakeup recognition, result:%{public}d", result);
385 OHOS::HDI::IntelligentVoice::Engine::V1_0::IntellVoiceEngineCallBackEvent event;
386 event.msgId = INTELL_VOICE_ENGINE_MSG_RECOGNIZE_COMPLETE;
387 event.result = static_cast<OHOS::HDI::IntelligentVoice::Engine::V1_0::IntellVoiceEngineErrors>(result);
388 event.info = info;
389 StateMsg msg(RECOGNIZE_COMPLETE, reinterpret_cast<void *>(&event),
390 sizeof(OHOS::HDI::IntelligentVoice::Engine::V1_0::IntellVoiceEngineCallBackEvent));
391 Handle(msg);
392 }
393
HandleSetParam(const StateMsg & msg,State &)394 int32_t WakeupEngineImpl::HandleSetParam(const StateMsg &msg, State & /* nextState */)
395 {
396 StringParam *param = reinterpret_cast<StringParam *>(msg.inMsg);
397 if (param == nullptr) {
398 INTELL_VOICE_LOG_INFO("param is nullptr");
399 return -1;
400 }
401
402 return EngineUtil::SetParameter(param->strParam);
403 }
404
HandleGetParam(const StateMsg & msg,State &)405 int32_t WakeupEngineImpl::HandleGetParam(const StateMsg &msg, State & /* nextState */)
406 {
407 StringParam *key = reinterpret_cast<StringParam *>(msg.inMsg);
408 StringParam *value = reinterpret_cast<StringParam *>(msg.outMsg);
409 if ((key == nullptr) || (value == nullptr)) {
410 INTELL_VOICE_LOG_INFO("key or value is nullptr");
411 return -1;
412 }
413
414 if (key->strParam == WAKEUP_SOURCE_CHANNEL) {
415 value->strParam = std::to_string(static_cast<uint32_t>(capturerOptions_.streamInfo.channels));
416 } else if (key->strParam == IS_CALLBACK_EXIST) {
417 if (adapterListener_ == nullptr) {
418 INTELL_VOICE_LOG_ERROR("adapterListener_ is nullptr");
419 value->strParam = "false";
420 } else {
421 value->strParam = adapterListener_->GetCallbackStatus();
422 }
423 } else {
424 value->strParam = EngineUtil::GetParameter(key->strParam);
425 }
426 INTELL_VOICE_LOG_INFO("key:%{public}s, value:%{public}s", key->strParam.c_str(), value->strParam.c_str());
427 return 0;
428 }
429
HandleInit(const StateMsg &,State & nextState)430 int32_t WakeupEngineImpl::HandleInit(const StateMsg & /* msg */, State &nextState)
431 {
432 INTELL_VOICE_LOG_INFO("enter");
433 if (!EngineUtil::CreateAdapterInner(EngineHostManager::GetInstance(), WAKEUP_ADAPTER_TYPE)) {
434 INTELL_VOICE_LOG_ERROR("failed to create adapter");
435 return -1;
436 }
437
438 if (!SetCallbackInner()) {
439 INTELL_VOICE_LOG_ERROR("failed to set callback");
440 return -1;
441 }
442 EngineUtil::SetWhisperVpr();
443 SetWakeupModel();
444 EngineUtil::SetLanguage();
445 EngineUtil::SetArea();
446 EngineUtil::SetSensibility();
447 EngineUtil::SetImproveParam();
448 SetDspFeatures();
449
450 IntellVoiceEngineInfo info = {
451 .wakeupPhrase = GetWakeupPhrase(),
452 .isPcmFromExternal = false,
453 .minBufSize = MIN_BUFFER_SIZE,
454 .sampleChannels = CHANNEL_CNT,
455 .bitsPerSample = BITS_PER_SAMPLE,
456 .sampleRate = SAMPLE_RATE,
457 };
458 if (AttachInner(info) != 0) {
459 INTELL_VOICE_LOG_ERROR("failed to attach");
460 return -1;
461 }
462
463 UpdateDspModel();
464
465 nextState = State(INITIALIZING);
466 return 0;
467 }
468
HandleInitDone(const StateMsg & msg,State & nextState)469 int32_t WakeupEngineImpl::HandleInitDone(const StateMsg &msg, State &nextState)
470 {
471 INTELL_VOICE_LOG_INFO("enter");
472 int32_t *result = reinterpret_cast<int32_t *>(msg.inMsg);
473 if ((result == nullptr) || (*result != 0)) {
474 INTELL_VOICE_LOG_ERROR("init done failed");
475 return -1;
476 }
477
478 nextState = State(INITIALIZED);
479 return 0;
480 }
481
HandleSetListener(const StateMsg & msg,State &)482 int32_t WakeupEngineImpl::HandleSetListener(const StateMsg &msg, State & /* nextState */)
483 {
484 SetListenerMsg *listenerMsg = reinterpret_cast<SetListenerMsg *>(msg.inMsg);
485 if (listenerMsg == nullptr || adapterListener_ == nullptr) {
486 INTELL_VOICE_LOG_ERROR("listenerMsg or adapter listener is nullptr");
487 return -1;
488 }
489
490 adapterListener_->SetCallback(listenerMsg->callback);
491 return 0;
492 }
493
HandleStart(const StateMsg & msg,State & nextState)494 int32_t WakeupEngineImpl::HandleStart(const StateMsg &msg, State &nextState)
495 {
496 int32_t *msgBody = reinterpret_cast<int32_t *>(msg.inMsg);
497 if (msgBody == nullptr) {
498 INTELL_VOICE_LOG_ERROR("msgBody is nullptr");
499 return -1;
500 }
501
502 if (*msgBody == PROXIMAL_WAKEUP_MODEL_UUID) {
503 channelId_ = CHANNEL_ID_1;
504 EngineUtil::SetParameter("WakeupType=3");
505 } else {
506 channelId_ = CHANNEL_ID_0;
507 EngineUtil::SetParameter("WakeupType=0");
508 }
509 INTELL_VOICE_LOG_INFO("enter, channel id is %{public}d", channelId_);
510
511 EngineUtil::SetParameter("VprTrdType=0;WakeupScene=0");
512 EngineUtil::SetScreenStatus();
513
514 if (adapter_ == nullptr) {
515 INTELL_VOICE_LOG_ERROR("adapter is nullptr");
516 return -1;
517 }
518
519 StartInfo info = {
520 .isLast = true,
521 };
522 if (adapter_->Start(info)) {
523 INTELL_VOICE_LOG_ERROR("start adapter failed");
524 return -1;
525 }
526
527 if (!CreateWakeupSourceStopCallback()) {
528 INTELL_VOICE_LOG_ERROR("create wakeup source stop callback failed");
529 adapter_->Stop();
530 return -1;
531 }
532
533 SetParamOnAudioStart(*msgBody);
534
535 if (!StartAudioSource()) {
536 INTELL_VOICE_LOG_ERROR("start audio source failed");
537 SetParamOnAudioStop();
538 adapter_->Stop();
539 return -1;
540 }
541
542 INTELL_VOICE_LOG_INFO("exit");
543 nextState = State(RECOGNIZING);
544 return 0;
545 }
546
HandleStop(const StateMsg &,State & nextState)547 int32_t WakeupEngineImpl::HandleStop(const StateMsg & /* msg */, State &nextState)
548 {
549 StopAudioSource();
550 EngineUtil::Stop();
551 nextState = State(INITIALIZED);
552 return 0;
553 }
554
HandleRecognizeComplete(const StateMsg & msg,State & nextState)555 int32_t WakeupEngineImpl::HandleRecognizeComplete(const StateMsg &msg, State &nextState)
556 {
557 OHOS::HDI::IntelligentVoice::Engine::V1_0::IntellVoiceEngineCallBackEvent *event =
558 reinterpret_cast<OHOS::HDI::IntelligentVoice::Engine::V1_0::IntellVoiceEngineCallBackEvent *>(msg.inMsg);
559 if (event == nullptr) {
560 INTELL_VOICE_LOG_ERROR("result is nullptr");
561 return -1;
562 }
563
564 if (adapterListener_ != nullptr) {
565 adapterListener_->Notify(*event);
566 }
567
568 if (event->result != 0) {
569 INTELL_VOICE_LOG_ERROR("wakeup failed");
570 StopAudioSource();
571 nextState = State(INITIALIZED);
572 } else {
573 nextState = State(RECOGNIZED);
574 }
575 EngineUtil::Stop();
576 return 0;
577 }
578
HandleStartCapturer(const StateMsg & msg,State & nextState)579 int32_t WakeupEngineImpl::HandleStartCapturer(const StateMsg &msg, State &nextState)
580 {
581 INTELL_VOICE_LOG_INFO("enter");
582 auto ret = IntellVoiceUtil::VerifySystemPermission(OHOS_MICROPHONE_PERMISSION);
583 if (ret != INTELLIGENT_VOICE_SUCCESS) {
584 return ret;
585 }
586
587 int32_t *msgBody = reinterpret_cast<int32_t *>(msg.inMsg);
588 if (msgBody == nullptr) {
589 INTELL_VOICE_LOG_ERROR("msgBody is nullptr");
590 return INTELLIGENT_VOICE_START_CAPTURER_FAILED;
591 }
592 channels_ = *msgBody;
593
594 callerTokenId_ = IPCSkeleton::GetCallingTokenID();
595 if (!IntellVoiceUtil::RecordPermissionPrivacy(OHOS_MICROPHONE_PERMISSION, callerTokenId_,
596 INTELL_VOICE_PERMISSION_START)) {
597 INTELL_VOICE_LOG_ERROR("record permissionPrivacy failed");
598 return -1;
599 }
600 nextState = State(READ_CAPTURER);
601 return 0;
602 }
603
HandleRead(const StateMsg & msg,State &)604 int32_t WakeupEngineImpl::HandleRead(const StateMsg &msg, State & /* nextState */)
605 {
606 CapturerData *capturerData = reinterpret_cast<CapturerData *>(msg.outMsg);
607 if (capturerData == nullptr) {
608 INTELL_VOICE_LOG_ERROR("capturer data is nullptr");
609 return -1;
610 }
611
612 auto ret = WakeupSourceProcess::Read(capturerData->data, channels_);
613 if (ret != 0) {
614 INTELL_VOICE_LOG_ERROR("read capturer data failed");
615 return ret;
616 }
617
618 ResetTimerDelay();
619 return 0;
620 }
621
HandleStopCapturer(const StateMsg &,State & nextState)622 int32_t WakeupEngineImpl::HandleStopCapturer(const StateMsg & /* msg */, State &nextState)
623 {
624 INTELL_VOICE_LOG_INFO("enter");
625 StopAudioSource();
626 EngineUtil::Stop();
627 if (CurrState() == State(READ_CAPTURER)) {
628 IntellVoiceUtil::RecordPermissionPrivacy(OHOS_MICROPHONE_PERMISSION, callerTokenId_,
629 INTELL_VOICE_PERMISSION_STOP);
630 }
631 nextState = State(INITIALIZED);
632 return 0;
633 }
634
HandleRecognizingTimeout(const StateMsg &,State & nextState)635 int32_t WakeupEngineImpl::HandleRecognizingTimeout(const StateMsg & /* msg */, State &nextState)
636 {
637 INTELL_VOICE_LOG_INFO("enter");
638 StopAudioSource();
639 EngineUtil::Stop();
640 nextState = State(INITIALIZED);
641 return 0;
642 }
643
HandleGetWakeupPcm(const StateMsg & msg,State &)644 int32_t WakeupEngineImpl::HandleGetWakeupPcm(const StateMsg &msg, State & /* nextState */)
645 {
646 CapturerData *capturerData = reinterpret_cast<CapturerData *>(msg.outMsg);
647 if (capturerData == nullptr) {
648 INTELL_VOICE_LOG_ERROR("capturer data is nullptr");
649 return -1;
650 }
651 auto ret = EngineUtil::GetWakeupPcm(capturerData->data);
652 if (ret != 0) {
653 INTELL_VOICE_LOG_ERROR("get wakeup pcm failed");
654 return ret;
655 }
656 return 0;
657 }
658
HandleResetAdapter(const StateMsg &,State & nextState)659 int32_t WakeupEngineImpl::HandleResetAdapter(const StateMsg & /* msg */, State &nextState)
660 {
661 INTELL_VOICE_LOG_INFO("enter");
662 if (!EngineUtil::CreateAdapterInner(EngineHostManager::GetInstance(), WAKEUP_ADAPTER_TYPE)) {
663 INTELL_VOICE_LOG_ERROR("failed to create adapter");
664 return -1;
665 }
666 SetWakeupModel();
667 adapter_->SetCallback(callback_);
668 EngineUtil::SetWhisperVpr();
669 EngineUtil::SetLanguage();
670 EngineUtil::SetArea();
671 EngineUtil::SetSensibility();
672 EngineUtil::SetImproveParam();
673 SetDspFeatures();
674
675 IntellVoiceEngineAdapterInfo adapterInfo = {
676 .wakeupPhrase = GetWakeupPhrase(),
677 .minBufSize = MIN_BUFFER_SIZE,
678 .sampleChannels = CHANNEL_CNT,
679 .bitsPerSample = BITS_PER_SAMPLE,
680 .sampleRate = SAMPLE_RATE,
681 };
682 if (adapter_->Attach(adapterInfo) != 0) {
683 INTELL_VOICE_LOG_ERROR("failed to attach");
684 EngineUtil::ReleaseAdapterInner(EngineHostManager::GetInstance());
685 return -1;
686 }
687
688 UpdateDspModel();
689
690 nextState = State(INITIALIZING);
691 return 0;
692 }
693
HandleRelease(const StateMsg &,State & nextState)694 int32_t WakeupEngineImpl::HandleRelease(const StateMsg & /* msg */, State &nextState)
695 {
696 DestroyWakeupSourceStopCallback();
697 StopAudioSource();
698 if (CurrState() == State(READ_CAPTURER)) {
699 IntellVoiceUtil::RecordPermissionPrivacy(OHOS_MICROPHONE_PERMISSION, callerTokenId_,
700 INTELL_VOICE_PERMISSION_STOP);
701 }
702 if (adapter_ != nullptr) {
703 adapter_->Detach();
704 ReleaseAdapterInner(EngineHostManager::GetInstance());
705 }
706 nextState = State(IDLE);
707 return 0;
708 }
709
SetWakeupModel()710 void WakeupEngineImpl::SetWakeupModel()
711 {
712 auto ret = EngineCallbackMessage::CallFunc(QUERY_SWITCH_STATUS, SHORTWORD_KEY);
713 bool switchstatus = false;
714 if (ret.has_value()) {
715 try {
716 switchstatus = std::any_cast<bool>(*ret);
717 } catch (const std::bad_any_cast&) {
718 INTELL_VOICE_LOG_ERROR("msg bus bad any cast");
719 return;
720 }
721 } else {
722 INTELL_VOICE_LOG_ERROR("msg bus return no value");
723 return;
724 }
725 if (switchstatus) {
726 adapter_->SetParameter("WakeupMode=1");
727 } else {
728 adapter_->SetParameter("WakeupMode=0");
729 }
730 }
731
UpdateDspModel()732 void WakeupEngineImpl::UpdateDspModel()
733 {
734 auto ret = EngineCallbackMessage::CallFunc(QUERY_SWITCH_STATUS, SHORTWORD_KEY);
735 bool switchstatus = false;
736 if (ret.has_value()) {
737 try {
738 switchstatus = std::any_cast<bool>(*ret);
739 } catch (const std::bad_any_cast&) {
740 INTELL_VOICE_LOG_ERROR("msg bus bad any cast");
741 return;
742 }
743 } else {
744 INTELL_VOICE_LOG_ERROR("msg bus return no value");
745 return;
746 }
747
748 if (switchstatus) {
749 SubscribeSwingEvent();
750 ProcDspModel(ReadDspModel(static_cast<OHOS::HDI::IntelligentVoice::Engine::V1_0::ContentType>(
751 OHOS::HDI::IntelligentVoice::Engine::V1_2::SHORT_WORD_DSP_MODEL)));
752 } else {
753 UnSubscribeSwingEvent();
754 ProcDspModel(ReadDspModel(OHOS::HDI::IntelligentVoice::Engine::V1_0::DSP_MODLE));
755 }
756 }
757
SubscribeSwingEvent()758 void WakeupEngineImpl::SubscribeSwingEvent()
759 {
760 INTELL_VOICE_LOG_INFO("enter");
761 isSubscribeSwingEvent_.store(true);
762 int32_t ret = SwingServiceWrapper::GetInstance().SubscribeSwingEvent(WAKEUP_CONFORMER_EVENT_TYPE,
763 WAKEUP_CONFORMER_DOMAIN_ID);
764 if (ret != 0) {
765 INTELL_VOICE_LOG_ERROR("load tiny model failed: %{public}d", ret);
766 return;
767 }
768 INTELL_VOICE_LOG_INFO("load tiny model");
769 }
770
UnSubscribeSwingEvent()771 void WakeupEngineImpl::UnSubscribeSwingEvent()
772 {
773 INTELL_VOICE_LOG_INFO("enter");
774 if (!isSubscribeSwingEvent_.load()) {
775 INTELL_VOICE_LOG_INFO("no need to UnSubscribeSwingEvent.");
776 return;
777 }
778 isSubscribeSwingEvent_.store(false);
779 int32_t ret = SwingServiceWrapper::GetInstance().UnSubscribeSwingEvent(WAKEUP_CONFORMER_EVENT_TYPE,
780 WAKEUP_CONFORMER_DOMAIN_ID);
781 if (ret != 0) {
782 INTELL_VOICE_LOG_ERROR("unload tiny model failed: %{public}d", ret);
783 return;
784 }
785 INTELL_VOICE_LOG_INFO("unload tiny model");
786 }
787
GetWakeupPhrase()788 std::string WakeupEngineImpl::GetWakeupPhrase()
789 {
790 std::string wakeupPhrase = HistoryInfoMgr::GetInstance().GetStringKVPair(KEY_WAKEUP_PHRASE);
791 if (wakeupPhrase.empty()) {
792 INTELL_VOICE_LOG_WARN("no phrase, use default phrase");
793 return std::string(DEFAULT_WAKEUP_PHRASE);
794 }
795
796 return wakeupPhrase;
797 }
798
ReadBufferCallback(uint8_t * buffer,uint32_t size,bool isEnd)799 void WakeupEngineImpl::ReadBufferCallback(uint8_t *buffer, uint32_t size, bool isEnd)
800 {
801 std::vector<std::vector<uint8_t>> audioData;
802 auto ret = IntellVoiceUtil::DeinterleaveAudioData(reinterpret_cast<int16_t *>(buffer),
803 size / sizeof(int16_t), static_cast<int32_t>(capturerOptions_.streamInfo.channels), audioData);
804 if ((!ret) || ((audioData.size() != static_cast<uint32_t>(capturerOptions_.streamInfo.channels))) ||
805 (channelId_ >= audioData.size())) {
806 INTELL_VOICE_LOG_ERROR("failed to deinterleave, ret:%{public}d, id:%{public}d", ret, channelId_);
807 return;
808 }
809 if ((adapter_ != nullptr) && !isEnd) {
810 if (channelId_ == CHANNEL_ID_1) { // whisper wakeup, need to write channel0 and channel1 data
811 std::vector<uint8_t> data(audioData[CHANNEL_ID_0].begin(), audioData[CHANNEL_ID_0].end());
812 data.insert(data.end(), audioData[CHANNEL_ID_1].begin(), audioData[CHANNEL_ID_1].end());
813 adapter_->WriteAudio(data);
814 } else {
815 adapter_->WriteAudio(audioData[channelId_]);
816 }
817 }
818 WakeupSourceProcess::Write(audioData);
819 }
820
821 #ifdef SUPPORT_WINDOW_MANAGER
SetFoldStatus()822 void WakeupEngineImpl::SetFoldStatus()
823 {
824 bool isFoldable = false;
825 FoldStatus newStatus = FoldStatus::EXPAND;
826 int32_t ret = GetFoldStatusInfo(isFoldable, newStatus);
827 if (ret != 0) {
828 INTELL_VOICE_LOG_ERROR("get fold status info err");
829 return;
830 }
831
832 INTELL_VOICE_LOG_INFO("audio_fold_status isFoldable:%{public}d, curStatus:%{public}d, newStatus:%{public}d",
833 isFoldable, curFoldStatus_, newStatus);
834 if (!isFoldable || newStatus == curFoldStatus_) {
835 return;
836 }
837
838 curFoldStatus_ = newStatus;
839 AsrAecMode aecMode = (newStatus == FoldStatus::FOLDED) ? AsrAecMode::FOLDED : AsrAecMode::EXPAND;
840 auto audioSystemManager = AudioSystemManager::GetInstance();
841 if (audioSystemManager == nullptr) {
842 INTELL_VOICE_LOG_ERROR("audioSystemManager is nullptr");
843 return;
844 }
845 audioSystemManager->SetAsrAecMode(aecMode);
846 INTELL_VOICE_LOG_INFO("audio_fold_status set to fwk success, aecMode:%{public}d", aecMode);
847 }
848
GetFoldStatusInfo(bool & isFoldable,FoldStatus & status)849 int32_t WakeupEngineImpl::GetFoldStatusInfo(bool &isFoldable, FoldStatus &status)
850 {
851 isFoldable = false;
852 status = FoldStatus::EXPAND;
853
854 auto triggerMgr = TriggerManager::GetInstance();
855 if (triggerMgr == nullptr) {
856 INTELL_VOICE_LOG_ERROR("trigger manager is nullptr");
857 return -1;
858 }
859
860 std::string keyValueList = triggerMgr->GetParameter("fold_status_info");
861 if (keyValueList == "") {
862 INTELL_VOICE_LOG_ERROR("no status info");
863 return -1;
864 }
865
866 std::map<std::string, std::string> kvpairs;
867 IntellVoiceUtil::SplitStringToKVPair(keyValueList, kvpairs);
868 for (auto it : kvpairs) {
869 if (it.first == std::string("is_foldable")) {
870 INTELL_VOICE_LOG_INFO("audio_fold_status is_foldable:%{public}s", it.second.c_str());
871 if (it.second == "true") {
872 isFoldable = true;
873 }
874 }
875 if (it.first == std::string("fold_status")) {
876 INTELL_VOICE_LOG_INFO("audio_fold_status fold_status:%{public}s", it.second.c_str());
877 if (it.second == "fold") {
878 status = FoldStatus::FOLDED;
879 }
880 }
881 }
882 INTELL_VOICE_LOG_INFO("audio_fold_status is_foldable:%{public}d, fold_status:%{public}d", isFoldable, status);
883 return 0;
884 }
885 #endif
886 }
887 }
888