• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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