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