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_manager.h"
16 
17 #include <chrono>
18 #include "iservice_registry.h"
19 #include "system_ability_definition.h"
20 #include "memory_guard.h"
21 #include "scope_guard.h"
22 #include "intell_voice_log.h"
23 #include "intell_voice_service_proxy.h"
24 
25 #define LOG_TAG "IntellVoiceManager"
26 
27 using namespace std;
28 using namespace OHOS::IntellVoiceEngine;
29 
30 namespace OHOS {
31 namespace IntellVoice {
32 constexpr int32_t LOAD_SA_TIMEOUT_S = 4; // 4s
33 
IntellVoiceManager()34 IntellVoiceManager::IntellVoiceManager()
35 {
36     INTELL_VOICE_LOG_INFO("enter");
37 }
38 
~IntellVoiceManager()39 IntellVoiceManager::~IntellVoiceManager()
40 {
41     INTELL_VOICE_LOG_INFO("enter");
42 }
43 
GetInstance()44 IntellVoiceManager *IntellVoiceManager::GetInstance()
45 {
46     static IntellVoiceManager manager;
47     if (!manager.Init()) {
48         return nullptr;
49     }
50     return &manager;
51 }
52 
Init()53 bool IntellVoiceManager::Init()
54 {
55     INTELL_VOICE_LOG_INFO("enter");
56     std::unique_lock<std::mutex> lock(mutex_);
57 
58     auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
59     if (samgr == nullptr) {
60         INTELL_VOICE_LOG_ERROR("get sa manager failed");
61         return false;
62     }
63 
64     auto object = samgr->LoadSystemAbility(INTELL_VOICE_SERVICE_ID, LOAD_SA_TIMEOUT_S);
65     if (object == nullptr) {
66         INTELL_VOICE_LOG_ERROR("Failed to load systemAbility");
67         return false;
68     }
69 
70     g_sProxy = iface_cast<IIntellVoiceService>(object);
71     if (g_sProxy != nullptr) {
72         INTELL_VOICE_LOG_INFO("init Service Proxy success");
73     }
74     INTELL_VOICE_LOG_INFO("Load systemAbility success");
75     return true;
76 }
77 
CreateIntellVoiceEngine(IntellVoiceEngineType type, sptr<IIntellVoiceEngine> &inst)78 int32_t IntellVoiceManager::CreateIntellVoiceEngine(IntellVoiceEngineType type, sptr<IIntellVoiceEngine> &inst)
79 {
80     INTELL_VOICE_LOG_INFO("enter");
81     if (g_sProxy == nullptr) {
82         INTELL_VOICE_LOG_ERROR("IntellVoiceService Proxy is null");
83         return -1;
84     }
85     return g_sProxy->CreateIntellVoiceEngine(type, inst);
86 }
87 
CreateHeadsetWakeupEngine()88 std::shared_ptr<WakeupIntellVoiceEngine> IntellVoiceManager::CreateHeadsetWakeupEngine()
89 {
90     INTELL_VOICE_LOG_INFO("enter");
91     WakeupIntelligentVoiceEngineDescriptor descriptor = {false, "小艺小艺"};
92     return std::make_shared<WakeupIntellVoiceEngine>(descriptor, INTELL_VOICE_HEADSET_WAKEUP);
93 }
94 
ReleaseIntellVoiceEngine(IntellVoiceEngineType type)95 int32_t IntellVoiceManager::ReleaseIntellVoiceEngine(IntellVoiceEngineType type)
96 {
97     INTELL_VOICE_LOG_INFO("enter");
98     if (g_sProxy == nullptr) {
99         INTELL_VOICE_LOG_ERROR("IntellVoiceService Proxy is null");
100         return -1;
101     }
102     return g_sProxy->ReleaseIntellVoiceEngine(type);
103 }
104 
RegisterServiceDeathRecipient(sptr<OHOS::IRemoteObject::DeathRecipient> callback)105 int32_t IntellVoiceManager::RegisterServiceDeathRecipient(sptr<OHOS::IRemoteObject::DeathRecipient> callback)
106 {
107     INTELL_VOICE_LOG_INFO("enter");
108     if (g_sProxy == nullptr) {
109         INTELL_VOICE_LOG_ERROR("IntellVoiceService Proxy is null");
110         return -1;
111     }
112 
113     if (callback == nullptr) {
114         INTELL_VOICE_LOG_ERROR("service death recipient is null");
115         return -1;
116     }
117 
118     bool ret = g_sProxy->AsObject()->AddDeathRecipient(callback);
119     if (!ret) {
120         INTELL_VOICE_LOG_ERROR("failed to add death recipient");
121         return -1;
122     }
123     return 0;
124 }
125 
DeregisterServiceDeathRecipient(sptr<OHOS::IRemoteObject::DeathRecipient> callback)126 int32_t IntellVoiceManager::DeregisterServiceDeathRecipient(sptr<OHOS::IRemoteObject::DeathRecipient> callback)
127 {
128     INTELL_VOICE_LOG_INFO("enter");
129     if (g_sProxy == nullptr) {
130         INTELL_VOICE_LOG_ERROR("IntellVoiceService Proxy is null");
131         return -1;
132     }
133 
134     if (callback == nullptr) {
135         INTELL_VOICE_LOG_ERROR("service death recipient is null");
136         return -1;
137     }
138 
139     bool ret = g_sProxy->AsObject()->RemoveDeathRecipient(callback);
140     if (!ret) {
141         INTELL_VOICE_LOG_ERROR("failed to remove death recipient");
142         return -1;
143     }
144     return 0;
145 }
146 
GetUploadFiles(int numMax, std::vector<UploadFilesInfo> &files)147 int32_t IntellVoiceManager::GetUploadFiles(int numMax, std::vector<UploadFilesInfo> &files)
148 {
149     INTELL_VOICE_LOG_INFO("enter, numMax: %{public}d", numMax);
150     CHECK_CONDITION_RETURN_RET(g_sProxy == nullptr, -1, "IntellVoiceService Proxy is null");
151     std::vector<UploadHdiFile> hdiFiles;
152     int32_t ret = g_sProxy->GetUploadFiles(numMax, hdiFiles);
153     if (ret != 0) {
154         INTELL_VOICE_LOG_ERROR("Get upload files failed, ret:%{public}d", ret);
155         return ret;
156     }
157 
158     if (hdiFiles.empty()) {
159         INTELL_VOICE_LOG_ERROR("no upload files");
160         return -1;
161     }
162     INTELL_VOICE_LOG_INFO("upload files size:%{public}u", static_cast<uint32_t>(hdiFiles.size()));
163     for (auto hdiFile : hdiFiles) {
164         UploadFilesInfo filesInfo;
165         filesInfo.type = hdiFile.type;
166         filesInfo.filesDescription = hdiFile.filesDescription;
167         for (auto content : hdiFile.filesContent) {
168             if (content == nullptr) {
169                 INTELL_VOICE_LOG_ERROR("fileContent is nullptr");
170                 continue;
171             }
172             std::vector<uint8_t> fileData;
173             if (GetFileDataFromAshmem(content, fileData) != 0) {
174                 INTELL_VOICE_LOG_ERROR("failed to file data from ashmem");
175                 continue;
176             }
177             filesInfo.filesContent.push_back(fileData);
178         }
179         files.push_back(filesInfo);
180     }
181     std::vector<UploadHdiFile>().swap(hdiFiles);
182     return 0;
183 }
184 
GetFileDataFromAshmem(sptr<Ashmem> ashmem, std::vector<uint8_t> &fileData)185 int32_t IntellVoiceManager::GetFileDataFromAshmem(sptr<Ashmem> ashmem, std::vector<uint8_t> &fileData)
186 {
187     if (ashmem == nullptr) {
188         INTELL_VOICE_LOG_ERROR("ashmem is nullptr");
189         return -1;
190     }
191 
192     ON_SCOPE_EXIT {
193         ashmem->UnmapAshmem();
194         ashmem->CloseAshmem();
195     };
196 
197     uint32_t size = static_cast<uint32_t>(ashmem->GetAshmemSize());
198     if (size == 0) {
199         INTELL_VOICE_LOG_ERROR("size is zero");
200         return -1;
201     }
202 
203     if (!ashmem->MapReadOnlyAshmem()) {
204         INTELL_VOICE_LOG_ERROR("map ashmem failed");
205         return -1;
206     }
207 
208     const uint8_t *buffer = static_cast<const uint8_t *>(ashmem->ReadFromAshmem(size, 0));
209     if (buffer == nullptr) {
210         INTELL_VOICE_LOG_ERROR("read from ashmem failed");
211         return -1;
212     }
213 
214     fileData.insert(fileData.begin(), buffer, buffer + size);
215     return 0;
216 }
217 
SetParameter(const std::string &key, const std::string &value)218 int32_t IntellVoiceManager::SetParameter(const std::string &key, const std::string &value)
219 {
220     INTELL_VOICE_LOG_INFO("enter, key:%{public}s, value:%{public}s", key.c_str(), value.c_str());
221     if (g_sProxy == nullptr) {
222         INTELL_VOICE_LOG_ERROR("IntellVoiceService Proxy is null");
223         return -1;
224     }
225     string keyValueList = key + "=" + value;
226     return g_sProxy->SetParameter(keyValueList);
227 }
228 
GetParameter(const std::string &key)229 std::string IntellVoiceManager::GetParameter(const std::string &key)
230 {
231     INTELL_VOICE_LOG_INFO("enter");
232     if (g_sProxy == nullptr) {
233         INTELL_VOICE_LOG_ERROR("IntellVoiceService Proxy is null");
234         return "";
235     }
236 
237     if (key.empty()) {
238         INTELL_VOICE_LOG_ERROR("key empty");
239         return "";
240     }
241 
242     return g_sProxy->GetParameter(key);
243 }
244 
GetWakeupSourceFiles(std::vector<WakeupSourceFile> &cloneFileInfo)245 int32_t IntellVoiceManager::GetWakeupSourceFiles(std::vector<WakeupSourceFile> &cloneFileInfo)
246 {
247     INTELL_VOICE_LOG_INFO("enter");
248     if (g_sProxy == nullptr) {
249         INTELL_VOICE_LOG_ERROR("IntellVoiceService Proxy is null");
250         return -1;
251     }
252 
253     std::vector<std::string> cloneFiles;
254     int ret = g_sProxy->GetWakeupSourceFilesList(cloneFiles);
255     if (ret != 0) {
256         INTELL_VOICE_LOG_ERROR("get clone list err");
257         return -1;
258     }
259 
260     WakeupSourceFile fileInfo;
261     size_t fileCount = cloneFiles.size();
262     cloneFiles.reserve(fileCount);
263 
264     for (size_t index = 0; index < fileCount; ++index) {
265         fileInfo.filePath = cloneFiles[index];
266         ret = g_sProxy->GetWakeupSourceFile(cloneFiles[index], fileInfo.fileContent);
267         if (ret != 0) {
268             INTELL_VOICE_LOG_ERROR("get clone file err");
269             return -1;
270         }
271         cloneFileInfo.push_back(fileInfo);
272     }
273 
274     return 0;
275 }
276 
EnrollWithWakeupFilesForResult(const std::vector<WakeupSourceFile> &cloneFileInfo, const std::string &wakeupInfo, const shared_ptr<IIntellVoiceUpdateCallback> callback)277 int32_t IntellVoiceManager::EnrollWithWakeupFilesForResult(const std::vector<WakeupSourceFile> &cloneFileInfo,
278     const std::string &wakeupInfo, const shared_ptr<IIntellVoiceUpdateCallback> callback)
279 {
280     INTELL_VOICE_LOG_INFO("enter");
281 
282     if (g_sProxy == nullptr) {
283         INTELL_VOICE_LOG_ERROR("IntellVoiceService proxy is null");
284         return -1;
285     }
286 
287     size_t fileCount = cloneFileInfo.size();
288     for (size_t index = 0; index < fileCount; ++index) {
289         int ret = g_sProxy->SendWakeupFile(cloneFileInfo[index].filePath, cloneFileInfo[index].fileContent);
290         if (ret != 0) {
291             INTELL_VOICE_LOG_ERROR("send clone file err, index:%{public}zu, size:%{public}zu, ret:%{public}d",
292                 index, fileCount, ret);
293             return -1;
294         }
295     }
296 
297     callback_ = sptr<UpdateCallbackInner>(new (std::nothrow) UpdateCallbackInner());
298     if (callback_ == nullptr) {
299         INTELL_VOICE_LOG_ERROR("callback_ is nullptr");
300         return -1;
301     }
302     callback_->SetUpdateCallback(callback);
303 
304     return g_sProxy->EnrollWithWakeupFilesForResult(wakeupInfo, callback_->AsObject());
305 }
306 
ClearUserData()307 int32_t IntellVoiceManager::ClearUserData()
308 {
309     INTELL_VOICE_LOG_INFO("enter");
310 
311     if (g_sProxy == nullptr) {
312         INTELL_VOICE_LOG_ERROR("IntellVoiceService proxy is nullptr");
313         return -1;
314     }
315 
316     return g_sProxy->ClearUserData();
317 }
318 }  // namespace IntellVoice
319 }  // namespace OHOS