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_trigger_adapter_impl.h"
16 #include "hdf_base.h"
17 #include "iproxy_broker.h"
18 #include "intell_voice_log.h"
19 #include "securec.h"
20 #include "scope_guard.h"
21 #include "memory_guard.h"
22
23 #undef HDF_LOG_TAG
24 #define HDF_LOG_TAG "TriggerAdapterImpl"
25
26 using namespace OHOS::HDI::IntelligentVoice::Trigger::V1_0;
27 using namespace OHOS::IntelligentVoice::Utils;
28
29 namespace OHOS {
30 namespace IntelligentVoice {
31 namespace Trigger {
IntellVoiceTriggerCallbackDevice(OHOS::sptr<IIntellVoiceTriggerCallback> callback)32 IntellVoiceTriggerCallbackDevice::IntellVoiceTriggerCallbackDevice(OHOS::sptr<IIntellVoiceTriggerCallback> callback)
33 : callback_(callback)
34 {}
35
~IntellVoiceTriggerCallbackDevice()36 IntellVoiceTriggerCallbackDevice::~IntellVoiceTriggerCallbackDevice()
37 {
38 callback_ = nullptr;
39 }
40
OnRecognitionHdiEvent(const IntellVoiceRecognitionEvent & event,int32_t cookie)41 void IntellVoiceTriggerCallbackDevice::OnRecognitionHdiEvent(const IntellVoiceRecognitionEvent &event, int32_t cookie)
42 {
43 if (callback_ == nullptr) {
44 INTELLIGENT_VOICE_LOGE("callback_ is nullptr");
45 return;
46 }
47 callback_->OnRecognitionHdiEvent(event, cookie);
48 }
49
IntellVoiceTriggerAdapterImpl(std::unique_ptr<ITrigger> adapter)50 IntellVoiceTriggerAdapterImpl::IntellVoiceTriggerAdapterImpl(std::unique_ptr<ITrigger> adapter)
51 : adapter_(std::move(adapter))
52 {}
53
~IntellVoiceTriggerAdapterImpl()54 IntellVoiceTriggerAdapterImpl::~IntellVoiceTriggerAdapterImpl()
55 {
56 adapter_ = nullptr;
57 }
58
GetProperties(IntellVoiceTriggerProperties & properties)59 int32_t IntellVoiceTriggerAdapterImpl::GetProperties(IntellVoiceTriggerProperties& properties)
60 {
61 return adapter_->GetProperties(properties);
62 }
63
LoadModel(const IntellVoiceTriggerModel & model,const sptr<IIntellVoiceTriggerCallback> & triggerCallback,int32_t cookie,int32_t & handle)64 int32_t IntellVoiceTriggerAdapterImpl::LoadModel(const IntellVoiceTriggerModel &model,
65 const sptr<IIntellVoiceTriggerCallback> &triggerCallback, int32_t cookie, int32_t &handle)
66 {
67 MemoryGuard memoryGuard;
68 std::shared_ptr<ITriggerCallback> cb = std::make_shared<IntellVoiceTriggerCallbackDevice>(triggerCallback);
69 if (cb == nullptr) {
70 INTELLIGENT_VOICE_LOGE("callback is nullptr");
71 return HDF_ERR_MALLOC_FAIL;
72 }
73
74 if (model.data == nullptr) {
75 INTELLIGENT_VOICE_LOGE("model data is nullptr");
76 return HDF_ERR_INVALID_PARAM;
77 }
78
79 ON_SCOPE_EXIT {
80 INTELLIGENT_VOICE_LOGI("close ashmem");
81 model.data->UnmapAshmem();
82 model.data->CloseAshmem();
83 };
84
85 std::vector<uint8_t> modelData;
86 if (GetModelDataFromAshmem(model.data, modelData) != static_cast<int32_t>(HDF_SUCCESS)) {
87 return HDF_ERR_INVALID_PARAM;
88 }
89
90 TriggerModel triggerModel(static_cast<OHOS::HDI::IntelligentVoice::Trigger::V1_2::IntellVoiceTriggerModelType>(
91 model.type), model.uid, modelData);
92 int32_t ret = adapter_->LoadIntellVoiceTriggerModel(triggerModel, cb, cookie, handle);
93 if (ret != 0) {
94 INTELLIGENT_VOICE_LOGE("failed to load model, ret:%{public}d", ret);
95 return ret;
96 }
97
98 RegisterDeathRecipient(handle, triggerCallback);
99 return ret;
100 }
101
UnloadModel(int32_t handle)102 int32_t IntellVoiceTriggerAdapterImpl::UnloadModel(int32_t handle)
103 {
104 MemoryGuard memoryGuard;
105 int32_t ret = adapter_->UnloadIntellVoiceTriggerModel(handle);
106 if (ret != 0) {
107 INTELLIGENT_VOICE_LOGE("failed to unload model");
108 return ret;
109 }
110
111 DeregisterDeathRecipient(handle);
112 return ret;
113 }
114
Start(int32_t handle)115 int32_t IntellVoiceTriggerAdapterImpl::Start(int32_t handle)
116 {
117 INTELLIGENT_VOICE_LOGE("Start");
118 MemoryGuard memoryGuard;
119 return adapter_->Start(handle);
120 }
121
Stop(int32_t handle)122 int32_t IntellVoiceTriggerAdapterImpl::Stop(int32_t handle)
123 {
124 MemoryGuard memoryGuard;
125 return adapter_->Stop(handle);
126 }
127
SetParams(const std::string & key,const std::string & value)128 int32_t IntellVoiceTriggerAdapterImpl::SetParams(const std::string &key, const std::string &value)
129 {
130 INTELLIGENT_VOICE_LOGI("enter");
131 MemoryGuard memoryGuard;
132 return adapter_->SetParams(key, value);
133 }
134
GetParams(const std::string & key,std::string & value)135 int32_t IntellVoiceTriggerAdapterImpl::GetParams(const std::string &key, std::string &value)
136 {
137 INTELLIGENT_VOICE_LOGI("enter");
138 MemoryGuard memoryGuard;
139 value = adapter_->GetParams(key);
140 return 0;
141 }
142
GetModelDataFromAshmem(sptr<Ashmem> ashmem,std::vector<uint8_t> & modelData)143 int32_t IntellVoiceTriggerAdapterImpl::GetModelDataFromAshmem(sptr<Ashmem> ashmem, std::vector<uint8_t> &modelData)
144 {
145 if (ashmem == nullptr) {
146 INTELLIGENT_VOICE_LOGE("ashmem is nullptr");
147 return HDF_ERR_INVALID_OBJECT;
148 }
149
150 uint32_t size = static_cast<uint32_t>(ashmem->GetAshmemSize());
151 if (size == 0) {
152 INTELLIGENT_VOICE_LOGE("size is zero");
153 return HDF_ERR_INVALID_PARAM;
154 }
155
156 if (!ashmem->MapReadOnlyAshmem()) {
157 INTELLIGENT_VOICE_LOGE("map ashmem failed");
158 return HDF_FAILURE;
159 }
160
161 const uint8_t *buffer = static_cast<const uint8_t *>(ashmem->ReadFromAshmem(size, 0));
162 if (buffer == nullptr) {
163 INTELLIGENT_VOICE_LOGE("read from ashmem failed");
164 return HDF_ERR_MALLOC_FAIL;
165 }
166
167 modelData.insert(modelData.begin(), buffer, buffer + size);
168 return HDF_SUCCESS;
169 }
170
RegisterDeathRecipient(int32_t handle,const sptr<IIntellVoiceTriggerCallback> & triggerCallback)171 bool IntellVoiceTriggerAdapterImpl::RegisterDeathRecipient(int32_t handle,
172 const sptr<IIntellVoiceTriggerCallback> &triggerCallback)
173 {
174 std::lock_guard<std::mutex> lock(mutex_);
175 INTELLIGENT_VOICE_LOGI("enter");
176 handleToCallbackMap_[handle] = triggerCallback;
177 sptr<IRemoteObject> object = OHOS::HDI::hdi_objcast<IIntellVoiceTriggerCallback>(triggerCallback);
178 if (object == nullptr) {
179 INTELLIGENT_VOICE_LOGE("object is nullptr");
180 return false;
181 }
182
183 auto it = callbackToHandleMap_.find(object.GetRefPtr());
184 if (it != callbackToHandleMap_.end()) {
185 it->second.insert(handle);
186 INTELLIGENT_VOICE_LOGI("callback already register, handle:%{public}d", handle);
187 return true;
188 }
189
190 sptr<IntellVoiceDeathRecipient> recipient = new (std::nothrow) IntellVoiceDeathRecipient(
191 std::bind(&IntellVoiceTriggerAdapterImpl::Clean, this, std::placeholders::_1), object.GetRefPtr());
192 if (recipient == nullptr) {
193 INTELLIGENT_VOICE_LOGE("create death recipient failed");
194 return false;
195 }
196
197 if (!object->AddDeathRecipient(recipient)) {
198 INTELLIGENT_VOICE_LOGE("add death recipient failed");
199 return false;
200 }
201
202 callbackToHandleMap_[object.GetRefPtr()].insert(handle);
203 deathRecipientMap_[object.GetRefPtr()] = recipient;
204 INTELLIGENT_VOICE_LOGI("register death recipient success");
205 return true;
206 }
207
DeregisterDeathRecipient(int32_t handle)208 void IntellVoiceTriggerAdapterImpl::DeregisterDeathRecipient(int32_t handle)
209 {
210 std::lock_guard<std::mutex> lock(mutex_);
211 auto callbackIter = handleToCallbackMap_.find(handle);
212 if (callbackIter == handleToCallbackMap_.end()) {
213 INTELLIGENT_VOICE_LOGE("failed to find callback");
214 return ;
215 }
216 sptr<IIntellVoiceTriggerCallback> callback = callbackIter->second;
217 handleToCallbackMap_.erase(callbackIter);
218
219 sptr<IRemoteObject> object = OHOS::HDI::hdi_objcast<IIntellVoiceTriggerCallback>(callback);
220 if (object == nullptr) {
221 INTELLIGENT_VOICE_LOGE("object is nullptr");
222 return;
223 }
224
225 auto handleSetIter = callbackToHandleMap_.find(object.GetRefPtr());
226 if (handleSetIter == callbackToHandleMap_.end()) {
227 INTELLIGENT_VOICE_LOGE("no handle set in callback, handle is: %{public}d", handle);
228 return;
229 }
230
231 auto handleIter = handleSetIter->second.find(handle);
232 if (handleIter == handleSetIter->second.end()) {
233 INTELLIGENT_VOICE_LOGE("no handle in handle set, handle is: %{public}d", handle);
234 return;
235 }
236
237 handleSetIter->second.erase(handleIter);
238 if (!handleSetIter->second.empty()) {
239 INTELLIGENT_VOICE_LOGI("handle set is not empty");
240 return;
241 }
242
243 if (deathRecipientMap_.count(object.GetRefPtr()) != 0) {
244 object->RemoveDeathRecipient(deathRecipientMap_[object.GetRefPtr()]);
245 deathRecipientMap_.erase(object.GetRefPtr());
246 }
247
248 callbackToHandleMap_.erase(object.GetRefPtr());
249 INTELLIGENT_VOICE_LOGI("handle set is empty, remove death recipient");
250 }
251
Clean(IRemoteObject * remote)252 void IntellVoiceTriggerAdapterImpl::Clean(IRemoteObject *remote)
253 {
254 std::lock_guard<std::mutex> lock(mutex_);
255 INTELLIGENT_VOICE_LOGI("enter");
256 if (remote == nullptr) {
257 INTELLIGENT_VOICE_LOGE("remote is nullptr");
258 return;
259 }
260
261 if (callbackToHandleMap_.count(remote) == 0) {
262 INTELLIGENT_VOICE_LOGE("no remote");
263 return;
264 }
265
266 MemoryGuard memoryGuard;
267 for (auto it = callbackToHandleMap_[remote].begin(); it != callbackToHandleMap_[remote].end(); ++it) {
268 INTELLIGENT_VOICE_LOGI("unload model, id is %{public}d", *it);
269 (void)adapter_->UnloadIntellVoiceTriggerModel(*it);
270 handleToCallbackMap_.erase(*it);
271 }
272
273 callbackToHandleMap_.erase(remote);
274 deathRecipientMap_.erase(remote);
275 }
276 } // namespace Trigger
277 } // namespace IntelligentVoice
278 } // namespace OHOS