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 "intell_voice_service_manager.h"
16
17 #include "intell_voice_log.h"
18 #include "engine_factory.h"
19 #include "wakeup_engine.h"
20 #include "trigger_manager.h"
21 #include "iservice_registry.h"
22 #include "system_ability_definition.h"
23 #include "intell_voice_generic_factory.h"
24 #include "trigger_detector_callback.h"
25 #include "memory_guard.h"
26
27 #define LOG_TAG "IntellVoiceServiceManager"
28
29 using namespace OHOS::IntellVoiceTrigger;
30 using namespace OHOS::IntellVoiceUtils;
31
32 namespace OHOS {
33 namespace IntellVoiceEngine {
34 const int32_t IntellVoiceServiceManager::g_enrollModelUuid = 1;
35 std::atomic<bool> IntellVoiceServiceManager::enrollResult_ = false;
36
37 std::unique_ptr<IntellVoiceServiceManager> IntellVoiceServiceManager::g_intellVoiceServiceMgr =
38 std::unique_ptr<IntellVoiceServiceManager>(new (std::nothrow) IntellVoiceServiceManager());
39
IntellVoiceServiceManager()40 IntellVoiceServiceManager::IntellVoiceServiceManager()
41 {
42 OHOS::IntellVoiceUtils::MemoryGuard memoryGuard;
43 historyInfoMgr_ = std::make_unique<HistoryInfoMgr>();
44 if (historyInfoMgr_ == nullptr) {
45 INTELL_VOICE_LOG_ERROR("historyInfoMgr_ is nullptr");
46 }
47 }
48
~IntellVoiceServiceManager()49 IntellVoiceServiceManager::~IntellVoiceServiceManager()
50 {
51 engines_.clear();
52 switchObserver_ = nullptr;
53 switchProvider_ = nullptr;
54 }
55
GetInstance()56 std::unique_ptr<IntellVoiceServiceManager> &IntellVoiceServiceManager::GetInstance()
57 {
58 return g_intellVoiceServiceMgr;
59 }
60
CreateEngine(IntellVoiceEngineType type)61 sptr<IIntellVoiceEngine> IntellVoiceServiceManager::CreateEngine(IntellVoiceEngineType type)
62 {
63 INTELL_VOICE_LOG_INFO("enter, type:%{public}d", type);
64 if (type == INTELL_VOICE_ENROLL) {
65 StopDetection();
66 }
67
68 std::lock_guard<std::mutex> lock(engineMutex_);
69
70 if (ApplyArbitration(type, ENGINE_EVENT_CREATE) != ARBITRATION_OK) {
71 INTELL_VOICE_LOG_ERROR("policy manager reject create engine, type:%{public}d", type);
72 return nullptr;
73 }
74
75 return CreateEngineInner(type);
76 }
77
CreateEngineInner(IntellVoiceEngineType type)78 sptr<IIntellVoiceEngine> IntellVoiceServiceManager::CreateEngineInner(IntellVoiceEngineType type)
79 {
80 INTELL_VOICE_LOG_INFO("create engine enter, type: %{public}d", type);
81 OHOS::IntellVoiceUtils::MemoryGuard memoryGuard;
82 auto it = engines_.find(type);
83 if (it != engines_.end() && it->second != nullptr) {
84 return it->second;
85 }
86
87 sptr<EngineBase> engine = EngineFactory::CreateEngineInst(type);
88 if (engine == nullptr) {
89 INTELL_VOICE_LOG_ERROR("create engine failed, type:%{public}d", type);
90 return nullptr;
91 }
92
93 engines_[type] = engine;
94 INTELL_VOICE_LOG_INFO("create engine ok");
95 return engine;
96 }
97
ReleaseEngine(IntellVoiceEngineType type)98 int32_t IntellVoiceServiceManager::ReleaseEngine(IntellVoiceEngineType type)
99 {
100 INTELL_VOICE_LOG_INFO("enter, type:%{public}d", type);
101 std::lock_guard<std::mutex> lock(engineMutex_);
102 auto ret = ReleaseEngineInner(type);
103 if (ret != 0) {
104 return ret;
105 }
106
107 if (type == INTELL_VOICE_ENROLL) {
108 if ((!GetEnrollResult()) && (!switchProvider_->QuerySwitchStatus())) {
109 std::thread(&IntellVoiceServiceManager::UnloadIntellVoiceService, this).detach();
110 return 0;
111 }
112
113 auto triggerMgr = TriggerManager::GetInstance();
114 if (triggerMgr == nullptr) {
115 INTELL_VOICE_LOG_WARN("trigger manager is nullptr");
116 return 0;
117 }
118 auto model = triggerMgr->GetModel(IntellVoiceServiceManager::GetEnrollModelUuid());
119 if (model == nullptr) {
120 INTELL_VOICE_LOG_WARN("no model");
121 return 0;
122 }
123
124 auto wakeupEngine = CreateEngineInner(INTELL_VOICE_WAKEUP);
125 if (wakeupEngine == nullptr) {
126 INTELL_VOICE_LOG_WARN("failed to create wakeup engine");
127 return 0;
128 }
129 CreateDetector();
130 if (switchProvider_->QuerySwitchStatus()) {
131 StartDetection();
132 }
133 }
134
135 return 0;
136 }
137
ReleaseEngineInner(IntellVoiceEngineType type)138 int32_t IntellVoiceServiceManager::ReleaseEngineInner(IntellVoiceEngineType type)
139 {
140 OHOS::IntellVoiceUtils::MemoryGuard memoryGuard;
141 auto it = engines_.find(type);
142 if (it == engines_.end()) {
143 INTELL_VOICE_LOG_ERROR("there is no engine(%{public}d) in list", type);
144 return -1;
145 }
146
147 it->second = nullptr;
148 engines_.erase(type);
149 return 0;
150 }
151
CreateSwitchProvider()152 void IntellVoiceServiceManager::CreateSwitchProvider()
153 {
154 INTELL_VOICE_LOG_INFO("enter");
155 switchObserver_ = sptr<SwitchObserver>(new (std::nothrow) SwitchObserver());
156 if (switchObserver_ == nullptr) {
157 INTELL_VOICE_LOG_ERROR("switchObserver_ is nullptr");
158 return;
159 }
160
161 switchObserver_->SetUpdateFunc([]() {
162 const auto &manager = IntellVoiceServiceManager::GetInstance();
163 if (manager != nullptr) {
164 manager->OnSwitchChange();
165 }
166 });
167
168 switchProvider_ = UniquePtrFactory<SwitchProvider>::CreateInstance();
169 if (switchProvider_ == nullptr) {
170 INTELL_VOICE_LOG_ERROR("switchProvider_ is nullptr");
171 return;
172 }
173
174 if (switchObserver_ != nullptr) {
175 switchProvider_->RegisterObserver(switchObserver_);
176 }
177 }
178
ReleaseSwitchProvider()179 void IntellVoiceServiceManager::ReleaseSwitchProvider()
180 {
181 if (switchProvider_ == nullptr) {
182 INTELL_VOICE_LOG_ERROR("switchProvider_ is nullptr");
183 return;
184 }
185
186 if (switchObserver_ != nullptr) {
187 switchProvider_->UnregisterObserver(switchObserver_);
188 }
189
190 switchProvider_ = nullptr;
191 }
192
CreateDetector()193 void IntellVoiceServiceManager::CreateDetector()
194 {
195 std::lock_guard<std::mutex> lock(detectorMutex_);
196 if (detector_ != nullptr) {
197 INTELL_VOICE_LOG_INFO("detector is already existed, no need to create");
198 return;
199 }
200
201 std::shared_ptr<TriggerDetectorCallback> cb = std::make_shared<TriggerDetectorCallback>([&]() { OnDetected(); });
202 if (cb == nullptr) {
203 INTELL_VOICE_LOG_ERROR("cb is nullptr");
204 return;
205 }
206
207 auto triggerMgr = TriggerManager::GetInstance();
208 if (triggerMgr == nullptr) {
209 INTELL_VOICE_LOG_ERROR("trigger manager is nullptr");
210 return;
211 }
212
213 detector_ = triggerMgr->CreateTriggerDetector(1, cb);
214 if (detector_ == nullptr) {
215 INTELL_VOICE_LOG_ERROR("detector_ is nullptr");
216 return;
217 }
218 }
219
StartDetection()220 void IntellVoiceServiceManager::StartDetection()
221 {
222 std::lock_guard<std::mutex> lock(detectorMutex_);
223 if (detector_ == nullptr) {
224 INTELL_VOICE_LOG_ERROR("detector_ is nullptr");
225 return;
226 }
227
228 detector_->StartRecognition();
229 }
230
StopDetection()231 void IntellVoiceServiceManager::StopDetection()
232 {
233 std::lock_guard<std::mutex> lock(detectorMutex_);
234 if (detector_ == nullptr) {
235 return;
236 }
237
238 detector_->StopRecognition();
239 }
240
OnDetected()241 void IntellVoiceServiceManager::OnDetected()
242 {
243 sptr<EngineBase> engine = nullptr;
244
245 {
246 std::lock_guard<std::mutex> lock(engineMutex_);
247 auto it = engines_.find(INTELL_VOICE_WAKEUP);
248 if ((it == engines_.end()) || (it->second == nullptr)) {
249 INTELL_VOICE_LOG_ERROR("wakeup engine is not existed");
250 return;
251 }
252
253 engine = it->second;
254 }
255
256 engine->OnDetected();
257 }
258
OnServiceStart()259 void IntellVoiceServiceManager::OnServiceStart()
260 {
261 auto triggerMgr = TriggerManager::GetInstance();
262 if (triggerMgr == nullptr) {
263 INTELL_VOICE_LOG_ERROR("trigger manager is nullptr");
264 return;
265 }
266 auto model = triggerMgr->GetModel(IntellVoiceServiceManager::GetEnrollModelUuid());
267 if (model == nullptr) {
268 INTELL_VOICE_LOG_INFO("no model");
269 return;
270 }
271
272 {
273 std::lock_guard<std::mutex> lock(engineMutex_);
274 sptr<EngineBase> wakeupEngine = EngineFactory::CreateEngineInst(INTELL_VOICE_WAKEUP);
275 if (wakeupEngine == nullptr) {
276 INTELL_VOICE_LOG_ERROR("wakeupEngine is nullptr");
277 return;
278 }
279 engines_[INTELL_VOICE_WAKEUP] = wakeupEngine;
280 }
281
282 CreateDetector();
283 StartDetection();
284 }
285
QuerySwitchStatus()286 bool IntellVoiceServiceManager::QuerySwitchStatus()
287 {
288 if (switchProvider_ == nullptr) {
289 INTELL_VOICE_LOG_ERROR("switchProvider_ is nullptr");
290 return false;
291 }
292 return switchProvider_->QuerySwitchStatus();
293 }
294
UnloadIntellVoiceService()295 void IntellVoiceServiceManager::UnloadIntellVoiceService()
296 {
297 {
298 std::lock_guard<std::mutex> lock(detectorMutex_);
299 if (detector_ != nullptr) {
300 detector_->UnloadTriggerModel();
301 }
302 }
303
304 {
305 std::lock_guard<std::mutex> lock(engineMutex_);
306 auto it = engines_.find(INTELL_VOICE_WAKEUP);
307 if ((it != engines_.end()) && (it->second != nullptr)) {
308 INTELL_VOICE_LOG_INFO("wakeup engine is existed");
309 it->second->Detach();
310 ReleaseEngineInner(INTELL_VOICE_WAKEUP);
311 }
312 }
313
314 auto systemAbilityMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
315 if (systemAbilityMgr == nullptr) {
316 INTELL_VOICE_LOG_ERROR("Failed to get systemabilitymanager.");
317 return;
318 }
319 int32_t ret = systemAbilityMgr->UnloadSystemAbility(INTELL_VOICE_SERVICE_ID);
320 if (ret != 0) {
321 INTELL_VOICE_LOG_ERROR("failed to unload intellvoice service, ret: %{public}d", ret);
322 return;
323 }
324 INTELL_VOICE_LOG_INFO("success to unload intellvoice service");
325 }
326
OnSwitchChange()327 void IntellVoiceServiceManager::OnSwitchChange()
328 {
329 if (switchProvider_ == nullptr) {
330 INTELL_VOICE_LOG_ERROR("switchProvider_ is nullptr");
331 return;
332 }
333
334 if (!switchProvider_->QuerySwitchStatus()) {
335 INTELL_VOICE_LOG_INFO("switch off");
336 UnloadIntellVoiceService();
337 }
338 }
339
ApplyArbitration(IntellVoiceEngineType type,EngineEvent event)340 int32_t IntellVoiceServiceManager::ApplyArbitration(IntellVoiceEngineType type, EngineEvent event)
341 {
342 INTELL_VOICE_LOG_INFO("enter");
343 switch (event) {
344 case ENGINE_EVENT_CREATE:
345 return CreateArbitration(type);
346 case ENGINE_EVENT_START:
347 return StartArbitration(type);
348 default:
349 INTELL_VOICE_LOG_INFO("unknown engine event:%{public}d", event);
350 break;
351 }
352 return ARBITRATION_OK;
353 }
354
CreateArbitration(IntellVoiceEngineType type)355 int32_t IntellVoiceServiceManager::CreateArbitration(IntellVoiceEngineType type)
356 {
357 INTELL_VOICE_LOG_INFO("enter");
358 if (type == INTELL_VOICE_ENROLL) {
359 auto wakeupEngineIt = engines_.find(INTELL_VOICE_WAKEUP);
360 if (wakeupEngineIt != engines_.end()) {
361 HandlePreemption(wakeupEngineIt->second);
362 }
363
364 auto enrollEngineIt = engines_.find(INTELL_VOICE_ENROLL);
365 if (enrollEngineIt != engines_.end()) {
366 HandleReplace(enrollEngineIt->second);
367 }
368 }
369 return ARBITRATION_OK;
370 }
371
StartArbitration(IntellVoiceEngineType type)372 int32_t IntellVoiceServiceManager::StartArbitration(IntellVoiceEngineType type)
373 {
374 INTELL_VOICE_LOG_INFO("enter");
375 if (type == INTELL_VOICE_WAKEUP) {
376 auto it = engines_.find(INTELL_VOICE_ENROLL);
377 if (it != engines_.end()) {
378 return ARBITRATION_REJECT;
379 }
380 }
381 return ARBITRATION_OK;
382 }
383
HandlePreemption(sptr<IIntellVoiceEngine> currentEngine)384 void IntellVoiceServiceManager::HandlePreemption(sptr<IIntellVoiceEngine> currentEngine)
385 {
386 INTELL_VOICE_LOG_INFO("enter");
387 if (currentEngine == nullptr) {
388 INTELL_VOICE_LOG_ERROR("failed to stop current engine, current engine is null");
389 return;
390 }
391 currentEngine->Stop();
392 }
393
HandleReplace(sptr<IIntellVoiceEngine> currentEngine)394 void IntellVoiceServiceManager::HandleReplace(sptr<IIntellVoiceEngine> currentEngine)
395 {
396 INTELL_VOICE_LOG_INFO("enter");
397 if (currentEngine == nullptr) {
398 INTELL_VOICE_LOG_ERROR("failed to detach current engine, current engine is null");
399 return;
400 }
401 currentEngine->Detach();
402 currentEngine = nullptr;
403 }
404 } // namespace IntellVoiceEngine
405 } // namespace OHOS
406