• 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_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(model.type, model.uid, modelData);
91     int32_t ret = adapter_->LoadIntellVoiceTriggerModel(triggerModel, cb, cookie, handle);
92     if (ret != 0) {
93         INTELLIGENT_VOICE_LOGE("failed to load model, ret:%{public}d", ret);
94         return ret;
95     }
96 
97     RegisterDeathRecipient(handle, triggerCallback);
98     return ret;
99 }
100 
UnloadModel(int32_t handle)101 int32_t IntellVoiceTriggerAdapterImpl::UnloadModel(int32_t handle)
102 {
103     MemoryGuard memoryGuard;
104     int32_t ret = adapter_->UnloadIntellVoiceTriggerModel(handle);
105     if (ret != 0) {
106         INTELLIGENT_VOICE_LOGE("failed to unload model");
107         return ret;
108     }
109 
110     DeregisterDeathRecipient(handle);
111     return ret;
112 }
113 
Start(int32_t handle)114 int32_t IntellVoiceTriggerAdapterImpl::Start(int32_t handle)
115 {
116     INTELLIGENT_VOICE_LOGE("Start");
117     MemoryGuard memoryGuard;
118     return adapter_->Start(handle);
119 }
120 
Stop(int32_t handle)121 int32_t IntellVoiceTriggerAdapterImpl::Stop(int32_t handle)
122 {
123     MemoryGuard memoryGuard;
124     return adapter_->Stop(handle);
125 }
126 
SetParams(const std::string & key,const std::string & value)127 int32_t IntellVoiceTriggerAdapterImpl::SetParams(const std::string &key, const std::string &value)
128 {
129     INTELLIGENT_VOICE_LOGI("enter");
130     MemoryGuard memoryGuard;
131     return adapter_->SetParams(key, value);
132 }
133 
GetParams(const std::string & key,std::string & value)134 int32_t IntellVoiceTriggerAdapterImpl::GetParams(const std::string &key, std::string &value)
135 {
136     INTELLIGENT_VOICE_LOGI("enter");
137     MemoryGuard memoryGuard;
138     value = adapter_->GetParams(key);
139     return 0;
140 }
141 
GetModelDataFromAshmem(sptr<Ashmem> ashmem,std::vector<uint8_t> & modelData)142 int32_t IntellVoiceTriggerAdapterImpl::GetModelDataFromAshmem(sptr<Ashmem> ashmem, std::vector<uint8_t> &modelData)
143 {
144     if (ashmem == nullptr) {
145         INTELLIGENT_VOICE_LOGE("ashmem is nullptr");
146         return HDF_ERR_INVALID_OBJECT;
147     }
148 
149     uint32_t size = static_cast<uint32_t>(ashmem->GetAshmemSize());
150     if (size == 0) {
151         INTELLIGENT_VOICE_LOGE("size is zero");
152         return HDF_ERR_INVALID_PARAM;
153     }
154 
155     if (!ashmem->MapReadOnlyAshmem()) {
156         INTELLIGENT_VOICE_LOGE("map ashmem failed");
157         return HDF_FAILURE;
158     }
159 
160     const uint8_t *buffer = static_cast<const uint8_t *>(ashmem->ReadFromAshmem(size, 0));
161     if (buffer == nullptr) {
162         INTELLIGENT_VOICE_LOGE("read from ashmem failed");
163         return HDF_ERR_MALLOC_FAIL;
164     }
165 
166     modelData.insert(modelData.begin(), buffer, buffer + size);
167     return HDF_SUCCESS;
168 }
169 
RegisterDeathRecipient(int32_t handle,const sptr<IIntellVoiceTriggerCallback> & triggerCallback)170 bool IntellVoiceTriggerAdapterImpl::RegisterDeathRecipient(int32_t handle,
171     const sptr<IIntellVoiceTriggerCallback> &triggerCallback)
172 {
173     std::lock_guard<std::mutex> lock(mutex_);
174     INTELLIGENT_VOICE_LOGI("enter");
175     handleToCallbackMap_[handle] = triggerCallback;
176     sptr<IRemoteObject> object = OHOS::HDI::hdi_objcast<IIntellVoiceTriggerCallback>(triggerCallback);
177     if (object == nullptr) {
178         INTELLIGENT_VOICE_LOGE("object is nullptr");
179         return false;
180     }
181 
182     auto it = callbackToHandleMap_.find(object.GetRefPtr());
183     if (it != callbackToHandleMap_.end()) {
184         it->second.insert(handle);
185         INTELLIGENT_VOICE_LOGI("callback already register, handle:%{public}d", handle);
186         return true;
187     }
188 
189     sptr<IntellVoiceDeathRecipient> recipient = new (std::nothrow) IntellVoiceDeathRecipient(
190         std::bind(&IntellVoiceTriggerAdapterImpl::Clean, this, std::placeholders::_1), object.GetRefPtr());
191     if (recipient == nullptr) {
192         INTELLIGENT_VOICE_LOGE("create death recipient failed");
193         return false;
194     }
195 
196     if (!object->AddDeathRecipient(recipient)) {
197         INTELLIGENT_VOICE_LOGE("add death recipient failed");
198         return false;
199     }
200 
201     callbackToHandleMap_[object.GetRefPtr()].insert(handle);
202     deathRecipientMap_[object.GetRefPtr()] = recipient;
203     INTELLIGENT_VOICE_LOGI("register death recipient success");
204     return true;
205 }
206 
DeregisterDeathRecipient(int32_t handle)207 void IntellVoiceTriggerAdapterImpl::DeregisterDeathRecipient(int32_t handle)
208 {
209     std::lock_guard<std::mutex> lock(mutex_);
210     auto callbackIter = handleToCallbackMap_.find(handle);
211     if (callbackIter == handleToCallbackMap_.end()) {
212         INTELLIGENT_VOICE_LOGE("failed to find callback");
213         return ;
214     }
215     sptr<IIntellVoiceTriggerCallback> callback = callbackIter->second;
216     handleToCallbackMap_.erase(callbackIter);
217 
218     sptr<IRemoteObject> object = OHOS::HDI::hdi_objcast<IIntellVoiceTriggerCallback>(callback);
219     if (object == nullptr) {
220         INTELLIGENT_VOICE_LOGE("object is nullptr");
221         return;
222     }
223 
224     auto handleSetIter = callbackToHandleMap_.find(object.GetRefPtr());
225     if (handleSetIter == callbackToHandleMap_.end()) {
226         INTELLIGENT_VOICE_LOGE("no handle set in callback, handle is: %{public}d", handle);
227         return;
228     }
229 
230     auto handleIter = handleSetIter->second.find(handle);
231     if (handleIter == handleSetIter->second.end()) {
232         INTELLIGENT_VOICE_LOGE("no handle in handle set, handle is: %{public}d", handle);
233         return;
234     }
235 
236     handleSetIter->second.erase(handleIter);
237     if (!handleSetIter->second.empty()) {
238         INTELLIGENT_VOICE_LOGI("handle set is not empty");
239         return;
240     }
241 
242     if (deathRecipientMap_.count(object.GetRefPtr()) != 0) {
243         object->RemoveDeathRecipient(deathRecipientMap_[object.GetRefPtr()]);
244         deathRecipientMap_.erase(object.GetRefPtr());
245     }
246 
247     callbackToHandleMap_.erase(object.GetRefPtr());
248     INTELLIGENT_VOICE_LOGI("handle set is empty, remove death recipient");
249 }
250 
Clean(IRemoteObject * remote)251 void IntellVoiceTriggerAdapterImpl::Clean(IRemoteObject *remote)
252 {
253     std::lock_guard<std::mutex> lock(mutex_);
254     INTELLIGENT_VOICE_LOGI("enter");
255     if (remote == nullptr) {
256         INTELLIGENT_VOICE_LOGE("remote is nullptr");
257         return;
258     }
259 
260     if (callbackToHandleMap_.count(remote) == 0) {
261         INTELLIGENT_VOICE_LOGE("no remote");
262         return;
263     }
264 
265     MemoryGuard memoryGuard;
266     for (auto it = callbackToHandleMap_[remote].begin(); it != callbackToHandleMap_[remote].end(); ++it) {
267         INTELLIGENT_VOICE_LOGI("unload model, id is %{public}d", *it);
268         (void)adapter_->UnloadIntellVoiceTriggerModel(*it);
269         handleToCallbackMap_.erase(*it);
270     }
271 
272     callbackToHandleMap_.erase(remote);
273     deathRecipientMap_.erase(remote);
274 }
275 }  // namespace Trigger
276 }  // namespace IntelligentVoice
277 }  // namespace OHOS