• 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 "headset_wakeup_engine_impl.h"
16 #include "audio_system_manager.h"
17 #include "adapter_callback_service.h"
18 #include "intell_voice_log.h"
19 #include "history_info_mgr.h"
20 #include "intell_voice_util.h"
21 #include "intell_voice_engine_manager.h"
22 #include "headset_host_manager.h"
23 #include "headset_wakeup_wrapper.h"
24 
25 #define LOG_TAG "HeadsetWakeupEngineImpl"
26 
27 using namespace OHOS::HDI::IntelligentVoice::Engine::V1_0;
28 using namespace OHOS::IntellVoiceUtils;
29 using namespace OHOS::AudioStandard;
30 using namespace std;
31 
32 namespace OHOS {
33 namespace IntellVoiceEngine {
34 static constexpr int64_t RECOGNIZING_TIMEOUT_US = 10 * 1000 * 1000; //10s
35 static constexpr int64_t RECOGNIZE_COMPLETE_TIMEOUT_US = 2 * 1000 * 1000; //2s
36 static constexpr int64_t READ_CAPTURER_TIMEOUT_US = 10 * 1000 * 1000; //10s
37 static constexpr uint32_t MAX_HEADSET_TASK_NUM = 200;
38 static const std::string HEADSET_THREAD_NAME = "HeadsetThread";
39 
HeadsetWakeupEngineImpl()40 HeadsetWakeupEngineImpl::HeadsetWakeupEngineImpl()
41     : ModuleStates(State(IDLE), "HeadsetWakeupEngineImpl"), TaskExecutor(HEADSET_THREAD_NAME, MAX_HEADSET_TASK_NUM)
42 {
43 }
44 
~HeadsetWakeupEngineImpl()45 HeadsetWakeupEngineImpl::~HeadsetWakeupEngineImpl()
46 {
47 }
48 
Init()49 bool HeadsetWakeupEngineImpl::Init()
50 {
51     if (!InitStates()) {
52         INTELL_VOICE_LOG_ERROR("init state failed");
53         return false;
54     }
55 
56     adapterListener_ = std::make_shared<WakeupAdapterListener>(
57         std::bind(&HeadsetWakeupEngineImpl::OnWakeupEvent, this, std::placeholders::_1));
58     if (adapterListener_ == nullptr) {
59         INTELL_VOICE_LOG_ERROR("adapterListener_ is nullptr");
60         return false;
61     }
62 
63     TaskExecutor::StartThread();
64     return true;
65 }
66 
InitStates()67 bool HeadsetWakeupEngineImpl::InitStates()
68 {
69     for (int i = IDLE; i <= READ_CAPTURER; i++) {
70         ForState(State(i))
71             .ACT(SET_LISTENER, HandleSetListener)
72             .ACT(SET_PARAM, HandleSetParam);
73     }
74 
75     ForState(IDLE)
76         .ACT(INIT, HandleInit)
77         .ACT(RESET_ADAPTER, HandleResetAdapter);
78 
79     ForState(INITIALIZING)
80         .ACT(INIT_DONE, HandleInitDone);
81 
82     ForState(INITIALIZED)
83         .ACT(START_RECOGNIZE, HandleStart);
84 
85     ForState(RECOGNIZING)
86         .WaitUntil(RECOGNIZING_TIMEOUT, std::bind(&HeadsetWakeupEngineImpl::HandleRecognizingTimeout,
87             this, std::placeholders::_1, std::placeholders::_2), RECOGNIZING_TIMEOUT_US)
88         .ACT(STOP_RECOGNIZE, HandleStop)
89         .ACT(RECOGNIZE_COMPLETE, HandleRecognizeComplete);
90 
91     ForState(RECOGNIZED)
92         .WaitUntil(RECOGNIZE_COMPLETE_TIMEOUT, std::bind(&HeadsetWakeupEngineImpl::HandleStopCapturer,
93             this, std::placeholders::_1, std::placeholders::_2), RECOGNIZE_COMPLETE_TIMEOUT_US)
94         .ACT(START_CAPTURER, HandleStartCapturer);
95 
96     ForState(READ_CAPTURER)
97         .WaitUntil(READ_CAPTURER_TIMEOUT, std::bind(&HeadsetWakeupEngineImpl::HandleStopCapturer,
98             this, std::placeholders::_1, std::placeholders::_2), READ_CAPTURER_TIMEOUT_US)
99         .ACT(READ, HandleRead)
100         .ACT(STOP_CAPTURER, HandleStopCapturer);
101 
102     FromState(INITIALIZING, READ_CAPTURER)
103         .ACT(RELEASE_ADAPTER, HandleRelease)
104         .ACT(RELEASE, HandleRelease);
105 
106     return IsStatesInitSucc();
107 }
108 
Handle(const StateMsg & msg)109 int32_t HeadsetWakeupEngineImpl::Handle(const StateMsg &msg)
110 {
111     if (!IsStatesInitSucc()) {
112         INTELL_VOICE_LOG_ERROR("failed to init state");
113         return -1;
114     }
115 
116     return ModuleStates::HandleMsg(msg);
117 }
118 
SetCallbackInner()119 bool HeadsetWakeupEngineImpl::SetCallbackInner()
120 {
121     INTELL_VOICE_LOG_INFO("enter");
122     if (adapter_ == nullptr) {
123         INTELL_VOICE_LOG_ERROR("adapter is nullptr");
124         return false;
125     }
126 
127     if (adapterListener_ == nullptr) {
128         INTELL_VOICE_LOG_ERROR("adapterListener_ is nullptr");
129         return false;
130     }
131 
132     callback_ = sptr<IIntellVoiceEngineCallback>(new (std::nothrow) AdapterCallbackService(adapterListener_));
133     if (callback_ == nullptr) {
134         INTELL_VOICE_LOG_ERROR("callback_ is nullptr");
135         return false;
136     }
137 
138     adapter_->SetCallback(callback_);
139     return true;
140 }
141 
AttachInner(const IntellVoiceEngineInfo & info)142 int32_t HeadsetWakeupEngineImpl::AttachInner(const IntellVoiceEngineInfo &info)
143 {
144     INTELL_VOICE_LOG_INFO("enter");
145     if (adapter_ == nullptr) {
146         INTELL_VOICE_LOG_ERROR("adapter is nullptr");
147         return -1;
148     }
149 
150     IntellVoiceEngineAdapterInfo adapterInfo = {
151     };
152 
153     return adapter_->Attach(adapterInfo);
154 }
155 
OnWakeupEvent(const OHOS::HDI::IntelligentVoice::Engine::V1_0::IntellVoiceEngineCallBackEvent & event)156 void HeadsetWakeupEngineImpl::OnWakeupEvent(
157     const OHOS::HDI::IntelligentVoice::Engine::V1_0::IntellVoiceEngineCallBackEvent &event)
158 {
159     INTELL_VOICE_LOG_INFO("enter, msgId:%{public}d, result:%{public}d", event.msgId, event.result);
160     if (event.msgId == INTELL_VOICE_ENGINE_MSG_INIT_DONE) {
161         TaskExecutor::AddAsyncTask([this, result = event.result]() { OnInitDone(result); },
162             "HeadsetWakeupEngineImpl::InitDone", false);
163     } else if (
164         event.msgId == static_cast<OHOS::HDI::IntelligentVoice::Engine::V1_0::IntellVoiceEngineMessageType>(
165             OHOS::HDI::IntelligentVoice::Engine::V1_2::INTELL_VOICE_ENGINE_MSG_HEADSET_RECOGNIZE_COMPLETE)) {
166         TaskExecutor::AddAsyncTask([this, result = event.result, info = event.info]() {
167             OnWakeupRecognition(result, info);
168             }, "HeadsetWakeupEngineImpl::RecgonizeComplete", false);
169     } else {
170     }
171 }
172 
OnInitDone(int32_t result)173 void HeadsetWakeupEngineImpl::OnInitDone(int32_t result)
174 {
175     INTELL_VOICE_LOG_INFO("enter, result:%{public}d", result);
176     StateMsg msg(INIT_DONE, &result, sizeof(int32_t));
177     Handle(msg);
178 }
179 
OnWakeupRecognition(int32_t result,const std::string & info)180 void HeadsetWakeupEngineImpl::OnWakeupRecognition(int32_t result, const std::string &info)
181 {
182     INTELL_VOICE_LOG_INFO("enter, result:%{public}d", result);
183     OHOS::HDI::IntelligentVoice::Engine::V1_0::IntellVoiceEngineCallBackEvent event;
184     event.msgId = static_cast<OHOS::HDI::IntelligentVoice::Engine::V1_0::IntellVoiceEngineMessageType>(
185         HDI::IntelligentVoice::Engine::V1_2::INTELL_VOICE_ENGINE_MSG_HEADSET_RECOGNIZE_COMPLETE);
186     event.result = static_cast<OHOS::HDI::IntelligentVoice::Engine::V1_0::IntellVoiceEngineErrors>(result);
187     event.info = info;
188     StateMsg msg(RECOGNIZE_COMPLETE, reinterpret_cast<void *>(&event),
189         sizeof(OHOS::HDI::IntelligentVoice::Engine::V1_0::IntellVoiceEngineCallBackEvent));
190     Handle(msg);
191 }
192 
HandleInit(const StateMsg &,State & nextState)193 int32_t HeadsetWakeupEngineImpl::HandleInit(const StateMsg & /* msg */, State &nextState)
194 {
195     INTELL_VOICE_LOG_INFO("enter");
196     if (!EngineUtil::CreateAdapterInner(HeadsetHostManager::GetInstance(), WAKEUP_ADAPTER_TYPE)) {
197         INTELL_VOICE_LOG_ERROR("failed to create adapter");
198         return -1;
199     }
200 
201     if (!SetCallbackInner()) {
202         INTELL_VOICE_LOG_ERROR("failed to set callback");
203         return -1;
204     }
205 
206     EngineUtil::SetLanguage();
207     EngineUtil::SetArea();
208     adapter_->SetParameter("model_path=/vendor/etc/audio/encoder.om");
209     IntellVoiceEngineInfo info = {};
210 
211     if (AttachInner(info) != 0) {
212         INTELL_VOICE_LOG_ERROR("failed to attach");
213         return -1;
214     }
215 
216     nextState = State(INITIALIZING);
217     return 0;
218 }
219 
HandleInitDone(const StateMsg & msg,State & nextState)220 int32_t HeadsetWakeupEngineImpl::HandleInitDone(const StateMsg &msg, State &nextState)
221 {
222     INTELL_VOICE_LOG_INFO("enter");
223     int32_t *result = reinterpret_cast<int32_t *>(msg.inMsg);
224     if ((result == nullptr) || (*result != 0)) {
225         INTELL_VOICE_LOG_ERROR("init done failed");
226         return -1;
227     }
228 
229     nextState = State(INITIALIZED);
230     return 0;
231 }
232 
HandleSetListener(const StateMsg & msg,State &)233 int32_t HeadsetWakeupEngineImpl::HandleSetListener(const StateMsg &msg, State & /* nextState */)
234 {
235     SetListenerMsg *listenerMsg = reinterpret_cast<SetListenerMsg *>(msg.inMsg);
236     if (listenerMsg == nullptr || adapterListener_ == nullptr) {
237         INTELL_VOICE_LOG_ERROR("listenerMsg or adapter listener is nullptr");
238         return -1;
239     }
240 
241     adapterListener_->SetCallback(listenerMsg->callback);
242     return 0;
243 }
244 
HandleStart(const StateMsg &,State & nextState)245 int32_t HeadsetWakeupEngineImpl::HandleStart(const StateMsg & /* msg */, State &nextState)
246 {
247     INTELL_VOICE_LOG_INFO("enter");
248     if (adapter_ == nullptr) {
249         INTELL_VOICE_LOG_ERROR("adapter is nullptr");
250         return -1;
251     }
252 
253     StartInfo info = {
254         .isLast = true,
255     };
256     if (adapter_->Start(info)) {
257         INTELL_VOICE_LOG_ERROR("start adapter failed");
258         return -1;
259     }
260 
261     if (!StartAudioSource()) {
262         INTELL_VOICE_LOG_ERROR("start audio source failed");
263         adapter_->Stop();
264         return -1;
265     }
266 
267     INTELL_VOICE_LOG_INFO("exit");
268     nextState = State(RECOGNIZING);
269     return 0;
270 }
271 
ReadThread()272 void HeadsetWakeupEngineImpl::ReadThread()
273 {
274     bool isEnd = false;
275     while (isReading_.load()) {
276         std::vector<uint8_t> audioStream;
277         bool hasAwakeWord = true;
278         int ret = HeadsetWakeupWrapper::GetInstance().ReadHeadsetStream(audioStream, hasAwakeWord);
279         if (ret != 1) {
280             INTELL_VOICE_LOG_INFO("finish reading, ret:%{public}d, isEnd:%{public}d, hasAwakeWord:%{public}d",
281                 ret, isEnd, hasAwakeWord);
282             if (!isEnd) {
283                 adapter_->SetParameter("end_of_pcm=true");
284             }
285             break;
286         }
287         if (hasAwakeWord && !isEnd) {
288             adapter_->WriteAudio(audioStream);
289         }
290         if (!hasAwakeWord && !isEnd) {
291             isEnd = true;
292             adapter_->SetParameter("end_of_pcm=true");
293         }
294         WakeupSourceProcess::Write({ audioStream });
295     }
296 }
297 
StartAudioSource()298 bool HeadsetWakeupEngineImpl::StartAudioSource()
299 {
300     INTELL_VOICE_LOG_INFO("enter");
301     isReading_.store(true);
302 
303     WakeupSourceProcess::Init(1);
304 
305     std::thread t1(std::bind(&HeadsetWakeupEngineImpl::ReadThread, this));
306     readThread_ = std::move(t1);
307     return true;
308 }
309 
StopAudioSource()310 void HeadsetWakeupEngineImpl::StopAudioSource()
311 {
312     if (!isReading_.load()) {
313         INTELL_VOICE_LOG_INFO("already stop");
314         return;
315     }
316     isReading_.store(false);
317     readThread_.join();
318     HeadsetWakeupWrapper::GetInstance().StopReadingStream();
319     WakeupSourceProcess::Release();
320 }
321 
HandleStop(const StateMsg &,State & nextState)322 int32_t HeadsetWakeupEngineImpl::HandleStop(const StateMsg & /* msg */, State &nextState)
323 {
324     StopAudioSource();
325     EngineUtil::Stop();
326     nextState = State(INITIALIZED);
327     return 0;
328 }
329 
HandleRecognizeComplete(const StateMsg & msg,State & nextState)330 int32_t HeadsetWakeupEngineImpl::HandleRecognizeComplete(const StateMsg &msg, State &nextState)
331 {
332     EngineUtil::Stop();
333     OHOS::HDI::IntelligentVoice::Engine::V1_0::IntellVoiceEngineCallBackEvent *event =
334         reinterpret_cast<OHOS::HDI::IntelligentVoice::Engine::V1_0::IntellVoiceEngineCallBackEvent *>(msg.inMsg);
335     if (event == nullptr) {
336         INTELL_VOICE_LOG_ERROR("event is nullptr");
337         return -1;
338     }
339 
340     adapterListener_->Notify(*event);
341 
342     if (event->result != 0) {
343         INTELL_VOICE_LOG_INFO("wakeup failed");
344         HeadsetWakeupWrapper::GetInstance().NotifyVerifyResult(false);
345         StopAudioSource();
346         nextState = State(INITIALIZED);
347     } else {
348         HeadsetWakeupWrapper::GetInstance().NotifyVerifyResult(true);
349         nextState = State(RECOGNIZED);
350     }
351     return 0;
352 }
353 
HandleStartCapturer(const StateMsg & msg,State & nextState)354 int32_t HeadsetWakeupEngineImpl::HandleStartCapturer(const StateMsg &msg, State &nextState)
355 {
356     INTELL_VOICE_LOG_INFO("enter");
357     int32_t *msgBody = reinterpret_cast<int32_t *>(msg.inMsg);
358     if (msgBody == nullptr) {
359         INTELL_VOICE_LOG_ERROR("msgBody is nullptr");
360         return -1;
361     }
362     channels_ = *msgBody;
363     nextState = State(READ_CAPTURER);
364     return 0;
365 }
366 
HandleRead(const StateMsg & msg,State &)367 int32_t HeadsetWakeupEngineImpl::HandleRead(const StateMsg &msg, State & /* nextState */)
368 {
369     CapturerData *capturerData = reinterpret_cast<CapturerData *>(msg.outMsg);
370     auto ret = WakeupSourceProcess::Read(capturerData->data, channels_);
371     if (ret != 0) {
372         INTELL_VOICE_LOG_ERROR("read capturer data failed");
373         return ret;
374     }
375 
376     ResetTimerDelay();
377     return 0;
378 }
379 
HandleStopCapturer(const StateMsg &,State & nextState)380 int32_t HeadsetWakeupEngineImpl::HandleStopCapturer(const StateMsg & /* msg */, State &nextState)
381 {
382     INTELL_VOICE_LOG_INFO("enter");
383     StopAudioSource();
384     nextState = State(INITIALIZED);
385     return 0;
386 }
387 
HandleRecognizingTimeout(const StateMsg &,State & nextState)388 int32_t HeadsetWakeupEngineImpl::HandleRecognizingTimeout(const StateMsg & /* msg */, State &nextState)
389 {
390     INTELL_VOICE_LOG_INFO("enter");
391     HeadsetWakeupWrapper::GetInstance().NotifyVerifyResult(false);
392     StopAudioSource();
393     EngineUtil::Stop();
394     nextState = State(INITIALIZED);
395     return 0;
396 }
397 
HandleResetAdapter(const StateMsg &,State & nextState)398 int32_t HeadsetWakeupEngineImpl::HandleResetAdapter(const StateMsg & /* msg */, State &nextState)
399 {
400     INTELL_VOICE_LOG_INFO("enter");
401     if (!EngineUtil::CreateAdapterInner(HeadsetHostManager::GetInstance(), WAKEUP_ADAPTER_TYPE)) {
402         INTELL_VOICE_LOG_ERROR("failed to create adapter");
403         return -1;
404     }
405 
406     adapter_->SetCallback(callback_);
407     EngineUtil::SetLanguage();
408     EngineUtil::SetArea();
409 
410     IntellVoiceEngineAdapterInfo adapterInfo = {
411     };
412 
413     if (adapter_->Attach(adapterInfo) != 0) {
414         INTELL_VOICE_LOG_ERROR("failed to attach");
415         EngineUtil::ReleaseAdapterInner(HeadsetHostManager::GetInstance());
416         return -1;
417     }
418 
419     nextState = State(INITIALIZING);
420     return 0;
421 }
422 
HandleRelease(const StateMsg &,State & nextState)423 int32_t HeadsetWakeupEngineImpl::HandleRelease(const StateMsg & /* msg */, State &nextState)
424 {
425     StopAudioSource();
426     if (adapter_ != nullptr) {
427         adapter_->Detach();
428         ReleaseAdapterInner(HeadsetHostManager::GetInstance());
429     }
430     nextState = State(IDLE);
431     return 0;
432 }
433 
HandleSetParam(const StateMsg & msg,State &)434 int32_t HeadsetWakeupEngineImpl::HandleSetParam(const StateMsg &msg, State & /* nextState */)
435 {
436     StringParam *param = reinterpret_cast<StringParam *>(msg.inMsg);
437     if (param == nullptr) {
438         INTELL_VOICE_LOG_INFO("param is nullptr");
439         return -1;
440     }
441 
442     return EngineUtil::SetParameter(param->strParam);
443 }
444 }
445 }