1 /*
2 * Copyright (C) 2025 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 <string>
16 #include <dlfcn.h>
17 #include "msdp_manager.h"
18 #include "message_parcel.h"
19 #include "extension_ability_manager.cpp"
20
21 namespace OHOS {
22 namespace Accessibility {
23 constexpr uint32_t FEATURE_USER_PREFERENCE_APP = 10;
24 constexpr uint32_t FEATURE_USER_FACE_ANGLE = 11;
25 constexpr uint32_t FEATURE_TIME_TUNNEL = 14;
26 constexpr uint32_t FEATURE_ENV_SOUND = 17;
27 constexpr int32_t MAX_APP_SIZE = 50;
28 const char* USER_STATUS_SO_NAME = "libuser_status_client.z.so";
29 const char* MSDP_SUBSCRIBE_CALLBACK_FUNC_NAME = "SubscribeCallback";
30 const char* MSDP_SUBSCRIBE_FUNC_NAME = "Subscribe";
31 const char* MSDP_UNSUBSCRIBE_FUNC_NAME = "Unsubscribe";
32 const std::string KEY_USER_STATUS_PREFERENCE_APP = "userStatusPreferenceApp";
33 const std::string KEY_FACE_ANGLE_STATUS = "userFaceAngleStatus";
34 const std::string TIME_TUNNEL_STATUS = "timeTunnelStatus";
35
36 typedef int32_t (*SubscribeCallbackFunc)(uint32_t feature, UserStatusDataCallbackFunc &callback);
37 typedef void (*SubscribeFunc)(uint32_t feature);
38 typedef void (*UnsubscribeFunc)(uint32_t feature);
39
UserStatusData()40 UserStatusData::UserStatusData() {}
41
~UserStatusData()42 UserStatusData::~UserStatusData() {}
43
GetFeature() const44 uint32_t UserStatusData::GetFeature() const
45 {
46 return feature_;
47 }
48
SetFeature(uint32_t feature)49 void UserStatusData::SetFeature(uint32_t feature)
50 {
51 feature_ = feature;
52 }
53
GetStatus() const54 std::string UserStatusData::GetStatus() const
55 {
56 return status_;
57 }
58
SetStatus(const std::string & status)59 void UserStatusData::SetStatus(const std::string &status)
60 {
61 status_ = status;
62 }
63
GetResult() const64 int32_t UserStatusData::GetResult() const
65 {
66 return result_;
67 }
68
SetResult(int32_t result)69 void UserStatusData::SetResult(int32_t result)
70 {
71 result_ = result;
72 }
73
GetErrorCode() const74 int32_t UserStatusData::GetErrorCode() const
75 {
76 return errorCode_;
77 }
78
SetErrorCode(int32_t errorCode)79 void UserStatusData::SetErrorCode(int32_t errorCode)
80 {
81 errorCode_ = errorCode;
82 }
83
GetResultApps() const84 std::vector<std::string> UserStatusData::GetResultApps() const
85 {
86 return resultApps_;
87 }
88
SetResultApps(const std::vector<std::string> resultApps)89 void UserStatusData::SetResultApps(const std::vector<std::string> resultApps)
90 {
91 resultApps_ = resultApps;
92 }
93
GetHpeDeviceId() const94 std::string UserStatusData::GetHpeDeviceId() const
95 {
96 return hpeDeviceId_;
97 }
98
SetHpeDeviceId(const std::string & hpeDeviceId)99 void UserStatusData::SetHpeDeviceId(const std::string &hpeDeviceId)
100 {
101 hpeDeviceId_ = hpeDeviceId;
102 }
103
GetCoordinateX() const104 int32_t UserStatusData::GetCoordinateX() const
105 {
106 return coordinateX_;
107 }
108
SetCoordinateX(int32_t coordinateX)109 void UserStatusData::SetCoordinateX(int32_t coordinateX)
110 {
111 coordinateX_ = coordinateX;
112 }
113
GetCoordinateY() const114 int32_t UserStatusData::GetCoordinateY() const
115 {
116 return coordinateY_;
117 }
118
SetCoordinateY(int32_t coordinateY)119 void UserStatusData::SetCoordinateY(int32_t coordinateY)
120 {
121 coordinateY_ = coordinateY;
122 }
123
GetPointerAction() const124 int32_t UserStatusData::GetPointerAction() const
125 {
126 return pointerAction_;
127 }
128
SetPointerAction(int32_t pointerAction)129 void UserStatusData::SetPointerAction(int32_t pointerAction)
130 {
131 pointerAction_ = pointerAction;
132 }
133
GetOrientation() const134 int32_t UserStatusData::GetOrientation() const
135 {
136 return orientation_;
137 }
138
SetOrientation(int32_t orientation)139 void UserStatusData::SetOrientation(int32_t orientation)
140 {
141 orientation_ = orientation;
142 }
143
Dump()144 std::string UserStatusData::Dump()
145 {
146 std::string dumpInfo = DumpBaseData();
147
148 if (feature_ == FEATURE_USER_PREFERENCE_APP) {
149 dumpInfo.append(", resultApps_=");
150 dumpInfo.append(std::to_string(resultApps_.size()));
151 for (const auto& app : resultApps_) {
152 dumpInfo.append(", ");
153 dumpInfo.append(app.c_str());
154 }
155 }
156 return dumpInfo;
157 }
158
DumpBaseData()159 std::string UserStatusData::DumpBaseData()
160 {
161 std::ostringstream dumpInfo;
162 dumpInfo << "feature=" << static_cast<uint32_t>(feature_)
163 << ", status=" << status_
164 << ", result=" << result_
165 << ", errorCode_=" << errorCode_;
166 if (feature_ == FEATURE_TIME_TUNNEL) {
167 dumpInfo << ", coordinateX=" << coordinateX_
168 << ", coordinateY=" << coordinateY_
169 << ", pointerAction=" << pointerAction_
170 << ", orientation=" << orientation_;
171 }
172 return dumpInfo.str();
173 }
174
Unmarshalling(Parcel & parcel)175 std::shared_ptr<UserStatusData> UserStatusData::Unmarshalling(Parcel &parcel)
176 {
177 auto statusData = std::make_shared<UserStatusData>();
178 if (!statusData->ReadFromParcel(parcel)) {
179 HILOG_ERROR("read from parcel failed");
180 return nullptr;
181 }
182 return statusData;
183 }
184
UnMarshallingFeature(Parcel & parcel)185 int32_t UserStatusData::UnMarshallingFeature(Parcel &parcel)
186 {
187 MessageParcel& msgParcel = static_cast<MessageParcel&>(parcel);
188 msgParcel.PrintBuffer(__FUNCTION__, __LINE__);
189 return parcel.ReadUint32();
190 }
191
Marshalling(Parcel & parcel) const192 bool UserStatusData::Marshalling(Parcel &parcel) const
193 {
194 if (!parcel.WriteUint32(feature_)) {
195 HILOG_ERROR("write features_ is failed");
196 return false;
197 }
198 if (!parcel.WriteInt32(result_)) {
199 HILOG_ERROR("write result_ is failed");
200 return false;
201 }
202 if (!parcel.WriteInt32(errorCode_)) {
203 HILOG_ERROR("write errorCode_ is failed");
204 return false;
205 }
206 if (!parcel.WriteString(status_)) {
207 HILOG_ERROR("write status_ is failed");
208 return false;
209 }
210
211 if (feature_ == FEATURE_USER_PREFERENCE_APP) {
212 int32_t appSize = static_cast<int32_t>(resultApps_.size());
213 if (appSize > MAX_APP_SIZE) {
214 appSize = MAX_APP_SIZE;
215 }
216 if (!parcel.WriteInt32(appSize)) {
217 HILOG_ERROR("write resultApps_ size is failed");
218 return false;
219 }
220 for (int32_t i = 0; i < appSize; ++i) {
221 if (!parcel.WriteString(resultApps_[i])) {
222 HILOG_ERROR("write resultApps_ item is failed");
223 return false;
224 }
225 }
226 }
227 if (feature_ == FEATURE_USER_FACE_ANGLE) {
228 if (!parcel.WriteString(hpeDeviceId_)) {
229 HILOG_ERROR("write hpeDeviceId_ is failed");
230 return false;
231 }
232 }
233 if (feature_ == FEATURE_TIME_TUNNEL) {
234 if (!WriteTimeTunnelData(parcel)) {
235 return false;
236 }
237 }
238 return true;
239 }
240
WriteTimeTunnelData(Parcel & parcel) const241 bool UserStatusData::WriteTimeTunnelData(Parcel &parcel) const
242 {
243 if (!parcel.WriteInt32(coordinateX_)) {
244 HILOG_ERROR("write coordinateX_ is failed");
245 return false;
246 }
247 if (!parcel.WriteInt32(coordinateY_)) {
248 HILOG_ERROR("write coordinateY_ is failed");
249 return false;
250 }
251 if (!parcel.WriteInt32(pointerAction_)) {
252 HILOG_ERROR("write pointerAction_ is failed");
253 return false;
254 }
255 if (!parcel.WriteInt32(orientation_)) {
256 HILOG_ERROR("write orientation_ is failed");
257 return false;
258 }
259
260 return true;
261 }
262
ReadFromParcel(Parcel & parcel)263 bool UserStatusData::ReadFromParcel(Parcel &parcel)
264 {
265 result_ = parcel.ReadInt32();
266 errorCode_ = parcel.ReadInt32();
267 status_ = parcel.ReadString();
268 if (status_.empty()) {
269 HILOG_ERROR("Read status_ failed");
270 return false;
271 }
272
273 if (status_ == KEY_USER_STATUS_PREFERENCE_APP) {
274 int32_t size = parcel.ReadInt32();
275 if (size > MAX_APP_SIZE || size < 0) {
276 HILOG_ERROR("Invalid app size: %{public}d", size);
277 return false;
278 }
279 std::string bundleName;
280 for (int32_t i = 0; i < size; ++i) {
281 bundleName = parcel.ReadString();
282 if (bundleName.empty()) {
283 HILOG_ERROR("Read bundle name failed, feature: %{public}d, result: %{public}d, errorCode: %{public}d",
284 feature_, result_, errorCode_);
285 return false;
286 }
287 resultApps_.push_back(bundleName);
288 }
289 }
290 if (status_ == KEY_FACE_ANGLE_STATUS) {
291 hpeDeviceId_ = parcel.ReadString();
292 }
293 if (status_ == TIME_TUNNEL_STATUS) {
294 coordinateX_ = parcel.ReadInt32();
295 coordinateY_ = parcel.ReadInt32();
296 pointerAction_ = parcel.ReadInt32();
297 orientation_ = parcel.ReadInt32();
298 }
299 return true;
300 }
301
MsdpManager()302 MsdpManager::MsdpManager()
303 {
304 handle_ = dlopen(USER_STATUS_SO_NAME, RTLD_NOW);
305 if (handle_ == nullptr) {
306 HILOG_ERROR("user status dlopen failed : %{public}s", dlerror());
307 }
308 }
309
~MsdpManager()310 MsdpManager::~MsdpManager()
311 {
312 if (handle_ != nullptr) {
313 dlclose(handle_);
314 }
315 }
316
GetInstance()317 MsdpManager& MsdpManager::GetInstance()
318 {
319 static MsdpManager instance;
320 return instance;
321 }
322
323
SubscribeVoiceRecognition()324 int32_t MsdpManager::SubscribeVoiceRecognition()
325 {
326 HILOG_INFO();
327 if (handle_ == nullptr) {
328 HILOG_ERROR("user status dlopen failed : %{public}s", dlerror());
329 return ERR_INVALID_STATE;
330 }
331 SubscribeCallbackFunc subscribeCallbackFunc = reinterpret_cast<SubscribeCallbackFunc>(dlsym(handle_,
332 MSDP_SUBSCRIBE_CALLBACK_FUNC_NAME));
333 if (subscribeCallbackFunc == nullptr) {
334 HILOG_ERROR("dlsym subscribeCallbackFunc failed : %{public}s", dlerror());
335 return ERR_INVALID_STATE;
336 }
337 SubscribeFunc subscribeFunc = reinterpret_cast<SubscribeFunc>(dlsym(handle_, MSDP_SUBSCRIBE_FUNC_NAME));
338 if (subscribeFunc == nullptr) {
339 HILOG_ERROR("dlsym subscribeFunc failed : %{public}s", dlerror());
340 return ERR_INVALID_STATE;
341 }
342 std::function<void(int32_t, std::shared_ptr<UserStatusData>)> func = [ = ](
343 int32_t callbackId, std::shared_ptr<UserStatusData> userStatusData) {
344 HILOG_INFO("voice recognition callback, Id: %{public}d, GetFeature: %{public}d, GetResult: %{public}d",
345 callbackId, userStatusData->GetFeature(), userStatusData->GetResult());
346
347 ExtensionAbilityManager::GetInstance().VoiceRecognize(userStatusData->GetResult());
348 };
349 int32_t ret = subscribeCallbackFunc(FEATURE_ENV_SOUND, func);
350 subscribeFunc(FEATURE_ENV_SOUND);
351 HILOG_INFO("userstatusClient.SubscribeCallback RET: %{public}d", ret);
352 return ret;
353 }
354
UnSubscribeVoiceRecognition()355 void MsdpManager::UnSubscribeVoiceRecognition()
356 {
357 HILOG_INFO();
358 if (handle_ == nullptr) {
359 HILOG_ERROR("user status dlopen failed : %{public}s", dlerror());
360 return;
361 }
362 UnsubscribeFunc unsubscribeFunc = reinterpret_cast<UnsubscribeFunc>(dlsym(handle_, MSDP_UNSUBSCRIBE_FUNC_NAME));
363 if (unsubscribeFunc == nullptr) {
364 HILOG_ERROR("dlsym unsubscribeFunc failed : %{public}s", dlerror());
365 return;
366 }
367 unsubscribeFunc(FEATURE_ENV_SOUND);
368 HILOG_INFO("userstatusClient.unsubscribeFunc");
369 }
370 } // namespace Accessibility
371 } // namespace OHOS
372