1 /*
2  * Copyright (c) 2023 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.h"
16 #include "ability_manager_client.h"
17 #include "idevmgr_hdi.h"
18 #include "intell_voice_service_manager.h"
19 #include "intell_voice_log.h"
20 #include "headset_host_manager.h"
21 
22 #define LOG_TAG "WakeupEngine"
23 
24 using namespace OHOS::IntellVoiceUtils;
25 using OHOS::HDI::DeviceManager::V1_0::IDeviceManager;
26 
27 namespace OHOS {
28 namespace IntellVoiceEngine {
WakeupEngine()29 WakeupEngine::WakeupEngine()
30 {
31     INTELL_VOICE_LOG_INFO("enter");
32 }
33 
~WakeupEngine()34 WakeupEngine::~WakeupEngine()
35 {
36     INTELL_VOICE_LOG_INFO("enter");
37 }
38 
OnDetected(int32_t uuid)39 void WakeupEngine::OnDetected(int32_t uuid)
40 {
41     INTELL_VOICE_LOG_INFO("enter, uuid is %{public}d", uuid);
42     {
43         std::lock_guard<std::mutex> lock(headsetMutex_);
44         if ((headsetImpl_ != nullptr) && (headsetImpl_->GetHeadsetAwakeState() == 1)) {
45             INTELL_VOICE_LOG_INFO("headset wakeup is exist");
46             return;
47         }
48     }
49 
50     std::thread([uuid]() { WakeupEngine::StartAbility(GetEventValue(uuid)); }).detach();
51     StateMsg msg(START_RECOGNIZE, &uuid, sizeof(int32_t));
52     if (ROLE(WakeupEngineImpl).Handle(msg) != 0) {
53         INTELL_VOICE_LOG_WARN("start failed");
54         std::thread([]() {
55             const auto &manager = IntellVoiceServiceManager::GetInstance();
56             if (manager != nullptr) {
57                 manager->HandleCloseWakeupSource();
58             }
59         }).detach();
60     }
61 }
62 
Init(const std::string &)63 bool WakeupEngine::Init(const std::string & /* param */)
64 {
65     StateMsg msg(INIT);
66     if (ROLE(WakeupEngineImpl).Handle(msg) != 0) {
67         return false;
68     }
69     return true;
70 }
71 
SetCallback(sptr<IRemoteObject> object)72 void WakeupEngine::SetCallback(sptr<IRemoteObject> object)
73 {
74     sptr<IIntelligentVoiceEngineCallback> callback = iface_cast<IIntelligentVoiceEngineCallback>(object);
75     if (callback == nullptr) {
76         INTELL_VOICE_LOG_WARN("clear callback");
77     }
78     SetListenerMsg listenerMsg(callback);
79     StateMsg msg(SET_LISTENER, &listenerMsg, sizeof(SetListenerMsg));
80     ROLE(WakeupEngineImpl).Handle(msg);
81     {
82         std::lock_guard<std::mutex> lock(headsetMutex_);
83         if (headsetImpl_ != nullptr) {
84             headsetImpl_->Handle(msg);
85         }
86     }
87 }
88 
Attach(const IntellVoiceEngineInfo &)89 int32_t WakeupEngine::Attach(const IntellVoiceEngineInfo & /* info */)
90 {
91     return 0;
92 }
93 
StartCapturer(int32_t channels)94 int32_t WakeupEngine::StartCapturer(int32_t channels)
95 {
96     StateMsg msg(START_CAPTURER, &channels, sizeof(int32_t));
97     return ROLE(WakeupEngineImpl).Handle(msg);
98 }
99 
Read(std::vector<uint8_t> & data)100 int32_t WakeupEngine::Read(std::vector<uint8_t> &data)
101 {
102     CapturerData capturerData;
103     StateMsg msg(READ, nullptr, 0, reinterpret_cast<void *>(&capturerData));
104     int32_t ret = ROLE(WakeupEngineImpl).Handle(msg);
105     if (ret != 0) {
106         INTELL_VOICE_LOG_ERROR("read failed, ret:%{public}d", ret);
107         return -1;
108     }
109 
110     data.swap(capturerData.data);
111     return 0;
112 }
113 
StopCapturer()114 int32_t WakeupEngine::StopCapturer()
115 {
116     StateMsg msg(STOP_CAPTURER);
117     return ROLE(WakeupEngineImpl).Handle(msg);
118 }
119 
NotifyHeadsetWakeEvent()120 int32_t WakeupEngine::NotifyHeadsetWakeEvent()
121 {
122     INTELL_VOICE_LOG_INFO("enter");
123     std::lock_guard<std::mutex> lock(headsetMutex_);
124     if (headsetImpl_ == nullptr) {
125         INTELL_VOICE_LOG_ERROR("headset impl is nullptr");
126         return -1;
127     }
128 
129     std::thread([]() { WakeupEngine::StartAbility("headset_event"); }).detach();
130 
131     StateMsg msg(START_RECOGNIZE);
132     return headsetImpl_->Handle(msg);
133 }
134 
HandleHeadsetOff()135 int32_t WakeupEngine::HandleHeadsetOff()
136 {
137     {
138         std::lock_guard<std::mutex> lock(headsetMutex_);
139         if (headsetImpl_ != nullptr) {
140             StateMsg msg(RELEASE);
141             if (headsetImpl_->Handle(msg) != 0) {
142                 INTELL_VOICE_LOG_ERROR("release headset wakeup engine impl failed");
143             }
144             headsetImpl_ = nullptr;
145         }
146     }
147     HeadsetHostManager::GetInstance().DeregisterEngineHDIDeathRecipient();
148     auto devmgr = IDeviceManager::Get();
149     if (devmgr == nullptr) {
150         INTELL_VOICE_LOG_ERROR("get devmgr failed");
151         return -1;
152     }
153     devmgr->UnloadDevice("tws_kws_service");
154     return 0;
155 }
156 
HandleHeadsetOn()157 int32_t WakeupEngine::HandleHeadsetOn()
158 {
159     auto devmgr = IDeviceManager::Get();
160     if (devmgr == nullptr) {
161         INTELL_VOICE_LOG_ERROR("get devmgr failed");
162         return -1;
163     }
164     devmgr->LoadDevice("tws_kws_service");
165     if (!HeadsetHostManager::GetInstance().Init()) {
166         INTELL_VOICE_LOG_ERROR("init headset host failed");
167         return -1;
168     }
169 
170     std::lock_guard<std::mutex> lock(headsetMutex_);
171     headsetImpl_ = UniquePtrFactory<HeadsetWakeupEngineImpl>::CreateInstance();
172     if (headsetImpl_ == nullptr) {
173         INTELL_VOICE_LOG_ERROR("failed to allocate headset impl");
174         return -1;
175     }
176 
177     StateMsg msg(INIT);
178     if (headsetImpl_->Handle(msg) != 0) {
179         INTELL_VOICE_LOG_ERROR("init headset wakeup engine impl failed");
180         return -1;
181     }
182     return 0;
183 }
184 
NotifyHeadsetHostEvent(HeadsetHostEventType event)185 int32_t WakeupEngine::NotifyHeadsetHostEvent(HeadsetHostEventType event)
186 {
187     INTELL_VOICE_LOG_INFO("enter, event:%{public}d", event);
188     if (event == HEADSET_HOST_OFF) {
189         return HandleHeadsetOff();
190     } else if (event == HEADSET_HOST_ON) {
191         return HandleHeadsetOn();
192     }
193 
194     INTELL_VOICE_LOG_WARN("invalid event:%{public}d", event);
195     return 0;
196 }
197 
Detach(void)198 int32_t WakeupEngine::Detach(void)
199 {
200     StateMsg msg(RELEASE);
201     return ROLE(WakeupEngineImpl).Handle(msg);
202 }
203 
Start(bool)204 int32_t WakeupEngine::Start(bool /* isLast */)
205 {
206     return 0;
207 }
208 
SetParameter(const std::string & keyValueList)209 int32_t WakeupEngine::SetParameter(const std::string &keyValueList)
210 {
211     StringParam param(keyValueList);
212     StateMsg msg(SET_PARAM, &param, sizeof(param));
213     return ROLE(WakeupEngineImpl).Handle(msg);
214 }
215 
GetParameter(const std::string & key)216 std::string WakeupEngine::GetParameter(const std::string &key)
217 {
218     StringParam keyParam(key);
219     StringParam valueParam;
220     StateMsg msg(GET_PARAM, &keyParam, sizeof(keyParam), &valueParam);
221     if (ROLE(WakeupEngineImpl).Handle(msg) != 0) {
222         return "";
223     }
224 
225     return valueParam.strParam;
226 }
227 
Stop()228 int32_t WakeupEngine::Stop()
229 {
230     StateMsg msg(STOP_RECOGNIZE);
231     return ROLE(WakeupEngineImpl).Handle(msg);
232 }
233 
GetWakeupPcm(std::vector<uint8_t> & data)234 int32_t WakeupEngine::GetWakeupPcm(std::vector<uint8_t> &data)
235 {
236     CapturerData capturerData;
237     StateMsg msg(GET_WAKEUP_PCM, nullptr, 0, reinterpret_cast<void *>(&capturerData));
238     int32_t ret = ROLE(WakeupEngineImpl).Handle(msg);
239     if (ret != 0) {
240         INTELL_VOICE_LOG_ERROR("get wakeup pcm failed, ret:%{public}d", ret);
241         return -1;
242     }
243 
244     data.swap(capturerData.data);
245     return 0;
246 }
247 
GetEventValue(int32_t uuid)248 std::string WakeupEngine::GetEventValue(int32_t uuid)
249 {
250     if (uuid == PROXIMAL_WAKEUP_MODEL_UUID) {
251         return "whisper_event";
252     }
253 
254     return "recognition_event";
255 }
256 
StartAbility(const std::string & event)257 void WakeupEngine::StartAbility(const std::string &event)
258 {
259     AAFwk::Want want;
260     HistoryInfoMgr &historyInfoMgr = HistoryInfoMgr::GetInstance();
261 
262     std::string bundleName = historyInfoMgr.GetWakeupEngineBundleName();
263     std::string abilityName = historyInfoMgr.GetWakeupEngineAbilityName();
264     INTELL_VOICE_LOG_INFO("bundleName:%{public}s, abilityName:%{public}s", bundleName.c_str(), abilityName.c_str());
265     if (bundleName.empty() || abilityName.empty()) {
266         INTELL_VOICE_LOG_ERROR("bundle name is empty or ability name is empty");
267         return;
268     }
269     want.SetElementName(bundleName, abilityName);
270     want.SetParam("serviceName", std::string("intell_voice"));
271     want.SetParam("servicePid", getpid());
272     want.SetParam("eventType", event);
273     AAFwk::AbilityManagerClient::GetInstance()->StartAbility(want);
274 }
275 
ResetAdapter()276 bool WakeupEngine::ResetAdapter()
277 {
278     StateMsg msg(RESET_ADAPTER);
279     return (ROLE(WakeupEngineImpl).Handle(msg) == 0 ? true : false);
280 }
281 
ReleaseAdapter()282 void WakeupEngine::ReleaseAdapter()
283 {
284     StateMsg msg(RELEASE_ADAPTER);
285     ROLE(WakeupEngineImpl).Handle(msg);
286 }
287 }  // namespace IntellVoice
288 }  // namespace OHOS
289