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_engine_manager_impl.h"
16 
17 #include <dlfcn.h>
18 #include <cinttypes>
19 #include "securec.h"
20 #include "hdf_base.h"
21 #include "securec.h"
22 #include "intell_voice_log.h"
23 #include "scope_guard.h"
24 #include "intell_voice_engine_adapter_impl.h"
25 
26 #undef HDF_LOG_TAG
27 #define HDF_LOG_TAG "IntelligentVoiceEngineManagerImpl"
28 
29 namespace OHOS {
30 namespace IntelligentVoice {
31 namespace Engine {
32 
33 #define CROSS_PROCESS_BUF_SIZE_LIMIT (256 *1024)
34 
IntellVoiceEngineManagerImplGetInstance(void)35 extern "C" IIntellVoiceEngineManager *IntellVoiceEngineManagerImplGetInstance(void)
36 {
37     return new (std::nothrow) IntellVoiceEngineManagerImpl();
38 }
39 
IntellVoiceEngineManagerImplRelease(IIntellVoiceEngineManager * mgr)40 extern "C" void IntellVoiceEngineManagerImplRelease(IIntellVoiceEngineManager *mgr)
41 {
42     INTELLIGENT_VOICE_LOGI("enter");
43     if (mgr == nullptr) {
44         INTELLIGENT_VOICE_LOGE("mgr is nullptr");
45         return;
46     }
47     delete mgr;
48 }
49 
LoadVendorLib()50 int32_t IntellVoiceEngineManagerImpl::LoadVendorLib()
51 {
52     std::string error;
53     const char *vendorLibPath = HDF_LIBRARY_FULL_PATH("libvendor_intell_voice_engine");
54     engineManagerPriv_.handle = dlopen(vendorLibPath, RTLD_LAZY);
55     if (engineManagerPriv_.handle == nullptr) {
56         error = dlerror();
57         INTELLIGENT_VOICE_LOGE("load path%{public}s, dlopen err=%{public}s", vendorLibPath, error.c_str());
58         return HDF_FAILURE;
59     }
60 
61     (void)dlerror(); // clear existing error
62 
63     engineManagerPriv_.getEngineManagerHalInst = reinterpret_cast<GetEngineManagerHalInstFunc>(dlsym(
64         engineManagerPriv_.handle, "GetIntellVoiceEngineManagerHalInst"));
65     if (engineManagerPriv_.getEngineManagerHalInst == nullptr) {
66         error = dlerror();
67         INTELLIGENT_VOICE_LOGE("dlsym GetIntellVoiceEngineManagerHalInst err=%{public}s", error.c_str());
68         dlclose(engineManagerPriv_.handle);
69         engineManagerPriv_.handle = nullptr;
70         return HDF_FAILURE;
71     }
72 
73     INTELLIGENT_VOICE_LOGI("load vendor lib success");
74 
75     return HDF_SUCCESS;
76 }
77 
UnloadVendorLib()78 void IntellVoiceEngineManagerImpl::UnloadVendorLib()
79 {
80     engineManagerPriv_.handle = nullptr;
81 }
82 
IntellVoiceEngineManagerImpl()83 IntellVoiceEngineManagerImpl::IntellVoiceEngineManagerImpl()
84 {
85     if (LoadVendorLib() == static_cast<int32_t>(HDF_SUCCESS)) {
86         inst_ = engineManagerPriv_.getEngineManagerHalInst();
87     }
88 }
89 
~IntellVoiceEngineManagerImpl()90 IntellVoiceEngineManagerImpl::~IntellVoiceEngineManagerImpl()
91 {
92     adapters_.clear();
93     inst_ = nullptr;
94     UnloadVendorLib();
95 }
96 
GetAdapterDescriptors(std::vector<IntellVoiceEngineAdapterDescriptor> & descs)97 int32_t IntellVoiceEngineManagerImpl::GetAdapterDescriptors(std::vector<IntellVoiceEngineAdapterDescriptor>& descs)
98 {
99     return HDF_SUCCESS;
100 }
101 
CreateAdapter(const IntellVoiceEngineAdapterDescriptor & descriptor,sptr<HDI::IntelligentVoice::Engine::V1_0::IIntellVoiceEngineAdapter> & adapter)102 int32_t IntellVoiceEngineManagerImpl::CreateAdapter(const IntellVoiceEngineAdapterDescriptor &descriptor,
103     sptr<HDI::IntelligentVoice::Engine::V1_0::IIntellVoiceEngineAdapter> &adapter)
104 {
105     return CreateAdapterInner(descriptor, adapter);
106 }
107 
CreateAdapter_V_2(const IntellVoiceEngineAdapterDescriptor & descriptor,sptr<HDI::IntelligentVoice::Engine::V1_2::IIntellVoiceEngineAdapter> & adapter)108 int32_t IntellVoiceEngineManagerImpl::CreateAdapter_V_2(const IntellVoiceEngineAdapterDescriptor &descriptor,
109     sptr<HDI::IntelligentVoice::Engine::V1_2::IIntellVoiceEngineAdapter> &adapter)
110 {
111     return CreateAdapterInner(descriptor, adapter);
112 }
113 
114 template<typename T>
CreateAdapterInner(const IntellVoiceEngineAdapterDescriptor & descriptor,sptr<T> & adapter)115 int32_t IntellVoiceEngineManagerImpl::CreateAdapterInner(const IntellVoiceEngineAdapterDescriptor &descriptor,
116     sptr<T> &adapter)
117 {
118     std::lock_guard<std::mutex> lock(mutex_);
119 
120     if (inst_ == nullptr) {
121         INTELLIGENT_VOICE_LOGE("inst is nullptr");
122         return HDF_FAILURE;
123     }
124 
125     std::unique_ptr<IEngine> engine = nullptr;
126     inst_->CreateAdapter(descriptor, engine);
127     if (engine == nullptr) {
128         INTELLIGENT_VOICE_LOGE("get adapter device from hal failed");
129         return HDF_FAILURE;
130     }
131 
132     adapter = sptr<HDI::IntelligentVoice::Engine::V1_2::IIntellVoiceEngineAdapter>
133         (new (std::nothrow) IntellVoiceEngineAdapterImpl(std::move(engine)));
134     if (adapter == nullptr) {
135         INTELLIGENT_VOICE_LOGE("malloc intell voice adapter server failed ");
136         return HDF_ERR_MALLOC_FAIL;
137     }
138 
139     adapters_.insert(std::make_pair(descriptor.adapterType, adapter));
140     return HDF_SUCCESS;
141 }
142 
ReleaseAdapter(const IntellVoiceEngineAdapterDescriptor & descriptor)143 int32_t IntellVoiceEngineManagerImpl::ReleaseAdapter(const IntellVoiceEngineAdapterDescriptor &descriptor)
144 {
145     std::lock_guard<std::mutex> lock(mutex_);
146 
147     if (inst_ == nullptr) {
148         INTELLIGENT_VOICE_LOGE("inst is nullptr");
149         return HDF_FAILURE;
150     }
151 
152     auto it = adapters_.find(descriptor.adapterType);
153     if (it == adapters_.end()) {
154         INTELLIGENT_VOICE_LOGW("can not find adapter, %{public}d", descriptor.adapterType);
155         return HDF_SUCCESS;
156     }
157 
158     inst_->ReleaseAdapter(descriptor);
159 
160     it->second = nullptr;
161     adapters_.erase(it);
162     return HDF_SUCCESS;
163 }
164 
SetDataOprCallback(const sptr<IIntellVoiceDataOprCallback> & dataOprCallback)165 int32_t IntellVoiceEngineManagerImpl::SetDataOprCallback(const sptr<IIntellVoiceDataOprCallback> &dataOprCallback)
166 {
167     INTELLIGENT_VOICE_LOGI("enter");
168     if (inst_ == nullptr) {
169         INTELLIGENT_VOICE_LOGE("inst is nullptr");
170         return HDF_FAILURE;
171     }
172 
173     std::shared_ptr<DataOprListener> listener = std::make_shared<DataOprListener>(dataOprCallback);
174     if (listener == nullptr) {
175         INTELLIGENT_VOICE_LOGE("listener is nullptr");
176         return HDF_ERR_MALLOC_FAIL;
177     }
178 
179     return inst_->SetDataOprListener(listener);
180 }
181 
DataOprListener(sptr<IIntellVoiceDataOprCallback> cb)182 DataOprListener::DataOprListener(sptr<IIntellVoiceDataOprCallback> cb) : cb_(cb)
183 {
184 }
185 
~DataOprListener()186 DataOprListener::~DataOprListener()
187 {
188     cb_ = nullptr;
189 }
190 
OnDataOprEvent(IntellVoiceDataOprType type,const OprDataInfo & inData,OprDataInfo & outData)191 int32_t DataOprListener::OnDataOprEvent(IntellVoiceDataOprType type, const OprDataInfo &inData, OprDataInfo &outData)
192 {
193     if (cb_ == nullptr) {
194         INTELLIGENT_VOICE_LOGE("cb is nullptr");
195         return HDF_FAILURE;
196     }
197 
198     sptr<Ashmem> inMem = nullptr;
199     if (type == OHOS::HDI::IntelligentVoice::Engine::V1_1::ENCRYPT_TYPE) {
200         inMem = CreateAshmemFromOprData(inData, "EnryptInIntellVoiceData");
201     } else if (type == OHOS::HDI::IntelligentVoice::Engine::V1_1::DECRYPT_TYPE) {
202         inMem = CreateAshmemFromOprData(inData, "DeryptInIntellVoiceData");
203     } else {
204         INTELLIGENT_VOICE_LOGE("invalid type:%{public}d", type);
205         return HDF_FAILURE;
206     }
207 
208     if (inMem == nullptr) {
209         INTELLIGENT_VOICE_LOGE("failed to create ashmem");
210         return HDF_FAILURE;
211     }
212 
213     sptr<Ashmem> outMem = nullptr;
214     ON_SCOPE_EXIT {
215         if (outMem != nullptr) {
216             INTELLIGENT_VOICE_LOGI("clear ashmem");
217             outMem->UnmapAshmem();
218             outMem->CloseAshmem();
219         }
220     };
221 
222     int32_t ret = cb_->OnIntellVoiceDataOprEvent(type, inMem, outMem);
223     if (ret != HDF_SUCCESS) {
224         INTELLIGENT_VOICE_LOGE("data opr failed");
225         return HDF_FAILURE;
226     }
227 
228     return FillOprDataFromAshmem(outMem, outData);
229 }
230 
CreateAshmemFromOprData(const OprDataInfo & data,const std::string & name)231 sptr<Ashmem> DataOprListener::CreateAshmemFromOprData(const OprDataInfo &data, const std::string &name)
232 {
233     if ((data.data == nullptr) || (data.size == 0)) {
234         INTELLIGENT_VOICE_LOGE("data is empty");
235         return nullptr;
236     }
237 
238     sptr<Ashmem> ashmem = OHOS::Ashmem::CreateAshmem(name.c_str(), data.size);
239     if (ashmem == nullptr) {
240         INTELLIGENT_VOICE_LOGE("failed to create ashmem");
241         return nullptr;
242     }
243 
244     ON_SCOPE_EXIT {
245         ashmem->UnmapAshmem();
246         ashmem->CloseAshmem();
247         ashmem = nullptr;
248     };
249 
250     if (!ashmem->MapReadAndWriteAshmem()) {
251         INTELLIGENT_VOICE_LOGE("failed to map ashmem");
252         return nullptr;
253     }
254 
255     if (!ashmem->WriteToAshmem(data.data.get(), data.size, 0)) {
256         INTELLIGENT_VOICE_LOGE("failed to write ashmem");
257         return nullptr;
258     }
259 
260     CANCEL_SCOPE_EXIT;
261     INTELLIGENT_VOICE_LOGI("create ashmem success,  size:%{public}u", data.size);
262     return ashmem;
263 }
264 
FillOprDataFromAshmem(const sptr<Ashmem> & ashmem,OprDataInfo & data)265 int32_t DataOprListener::FillOprDataFromAshmem(const sptr<Ashmem> &ashmem, OprDataInfo &data)
266 {
267     if (ashmem == nullptr) {
268         INTELLIGENT_VOICE_LOGE("ashmem is nullptr");
269         return HDF_FAILURE;
270     }
271 
272     uint32_t size = static_cast<uint32_t>(ashmem->GetAshmemSize());
273     if (size == 0) {
274         INTELLIGENT_VOICE_LOGE("size is zero");
275         return HDF_FAILURE;
276     }
277 
278     if (!ashmem->MapReadOnlyAshmem()) {
279         INTELLIGENT_VOICE_LOGE("map ashmem failed");
280         return HDF_FAILURE;
281     }
282 
283     const uint8_t *mem = static_cast<const uint8_t *>(ashmem->ReadFromAshmem(size, 0));
284     if (mem == nullptr) {
285         INTELLIGENT_VOICE_LOGE("read from ashmem failed");
286         return HDF_FAILURE;
287     }
288 
289     data.data = std::shared_ptr<char>(new char[size], [](char *p) { delete[] p; });
290     if (data.data == nullptr) {
291         INTELLIGENT_VOICE_LOGE("allocate data failed");
292         return HDF_FAILURE;
293     }
294 
295     (void)memcpy_s(data.data.get(), size, mem, size);
296     data.size = size;
297     return HDF_SUCCESS;
298 }
299 
GetUploadFiles(int32_t numMax,std::vector<UploadHdiFile> & files)300 int32_t IntellVoiceEngineManagerImpl::GetUploadFiles(int32_t numMax, std::vector<UploadHdiFile> &files)
301 {
302     if (inst_ == nullptr) {
303         INTELLIGENT_VOICE_LOGE("inst is nullptr");
304         return HDF_FAILURE;
305     }
306 
307     if (inst_->GetUploadFiles(numMax, files) != 0) {
308         INTELLIGENT_VOICE_LOGE("getReportFile failed");
309         return HDF_FAILURE;
310     }
311     return HDF_SUCCESS;
312 }
313 
GetCloneFilesList(std::vector<std::string> & cloneFiles)314 int32_t IntellVoiceEngineManagerImpl::GetCloneFilesList(std::vector<std::string> &cloneFiles)
315 {
316     if (inst_ == nullptr) {
317         INTELLIGENT_VOICE_LOGE("inst is nullptr");
318         return HDF_FAILURE;
319     }
320 
321     return inst_->GetCloneFilesList(cloneFiles);
322 }
323 
GetCloneFile(const std::string & filePath,std::vector<uint8_t> & buffer)324 int32_t IntellVoiceEngineManagerImpl::GetCloneFile(const std::string &filePath, std::vector<uint8_t> &buffer)
325 {
326     if (inst_ == nullptr) {
327         INTELLIGENT_VOICE_LOGE("inst is nullptr");
328         return HDF_FAILURE;
329     }
330 
331     std::shared_ptr<uint8_t> data = nullptr;
332     uint32_t size = 0;
333 
334     int32_t ret = inst_->GetCloneFile(filePath, data, size);
335     if (ret != 0) {
336         INTELLIGENT_VOICE_LOGE("get clone file fail");
337         return ret;
338     }
339 
340     if (filePath.empty()) {
341         INTELLIGENT_VOICE_LOGE("file path is empty");
342         return HDF_FAILURE;
343     }
344 
345     if (data == nullptr) {
346         INTELLIGENT_VOICE_LOGE("data is nullptr");
347         return HDF_FAILURE;
348     }
349 
350     if (size == 0 || size > CROSS_PROCESS_BUF_SIZE_LIMIT) {
351         INTELLIGENT_VOICE_LOGE("size is invalid %{public}u", size);
352         return HDF_FAILURE;
353     }
354 
355     buffer.resize(size);
356     ret = memcpy_s(&buffer[0], size, data.get(), size);
357     if (ret != 0) {
358         INTELLIGENT_VOICE_LOGE("memcpy err");
359         return HDF_FAILURE;
360     }
361 
362     return 0;
363 }
364 
SendCloneFile(const std::string & filePath,const std::vector<uint8_t> & buffer)365 int32_t IntellVoiceEngineManagerImpl::SendCloneFile(const std::string &filePath, const std::vector<uint8_t> &buffer)
366 {
367     if (inst_ == nullptr) {
368         INTELLIGENT_VOICE_LOGE("inst is nullptr");
369         return HDF_FAILURE;
370     }
371 
372     if (filePath.empty()) {
373         INTELLIGENT_VOICE_LOGE("file path is empty");
374         return HDF_FAILURE;
375     }
376 
377     if (buffer.data() == nullptr) {
378         INTELLIGENT_VOICE_LOGE("data is nullptr");
379         return HDF_FAILURE;
380     }
381 
382     if (buffer.size() == 0 || buffer.size() > CROSS_PROCESS_BUF_SIZE_LIMIT) {
383         INTELLIGENT_VOICE_LOGE("size %{public}u is invalid", static_cast<uint32_t>(buffer.size()));
384         return HDF_FAILURE;
385     }
386 
387     return inst_->SendCloneFile(filePath, buffer.data(), buffer.size());
388 }
389 
ClearUserWakeupData(const std::string & wakeupPhrase)390 int32_t IntellVoiceEngineManagerImpl::ClearUserWakeupData(const std::string &wakeupPhrase)
391 {
392     if (inst_ == nullptr) {
393         INTELLIGENT_VOICE_LOGE("inst is nullptr, failed to clear user wakup data");
394         return HDF_FAILURE;
395     }
396 
397     return inst_->ClearUserWakeupData(wakeupPhrase);
398 }
399 }
400 }
401 }
402