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
16 #include <sstream>
17 #include <map>
18
19 #include "ohos.driver.deviceManager.impl.hpp"
20 #include "ani_remote_object.h"
21 #include "ohos.driver.deviceManager.impl.h"
22 #include "ohos.driver.deviceManager.proj.hpp"
23 #include "stdexcept"
24 #include "taihe/runtime.hpp"
25 #include "edm_errors.h"
26
27 using namespace taihe;
28 using namespace ohos::driver::deviceManager;
29 namespace OHOS {
30 namespace ExternalDeviceManager {
31 constexpr int32_t ANI_SCOPE_SIZE = 16;
32 constexpr uint16_t TWO_PARAMETERS = 2;
33
34 static const std::map<int32_t, std::string> ERROR_MESSAGES = {
35 {SERVICE_EXCEPTION, "ExternalDeviceManager service exception."},
36 {PERMISSION_DENIED, "Permission denied."},
37 {PERMISSION_NOT_SYSTEM_APP, "Permission denied. A non-system application cannot call a system API."},
38 {PARAMETER_ERROR, "The parameter check failed."},
39 {SERVICE_EXCEPTION_NEW, "ExternalDeviceManager service exception."},
40 {SERVICE_NOT_ALLOW_ACCESS, "Driver does not allow application access."},
41 {SERVICE_NOT_BOUND, "There is no binding relationship between the application and the driver."}
42 };
43 static std::mutex mapMutex;
44 static std::map<uint64_t, OHOS::sptr<AsyncData>> g_callbackMap = {};
45 static OHOS::ExternalDeviceManager::DriverExtMgrClient &g_edmClient =
46 OHOS::ExternalDeviceManager::DriverExtMgrClient::GetInstance();
47 static OHOS::sptr<DeviceManagerCallback> g_edmCallback = new (std::nothrow) DeviceManagerCallback {};
48 static thread_local std::shared_ptr<OHOS::AppExecFwk::EventHandler> mainHandler = nullptr;
49
SendEventToMainThread(const std::function<void ()> func)50 static bool SendEventToMainThread(const std::function<void()> func)
51 {
52 EDM_LOGD(MODULE_DEV_MGR, "SendEventToMainThread begin");
53 if (func == nullptr) {
54 EDM_LOGE(MODULE_DEV_MGR, "func is nullptr!");
55 return false;
56 }
57
58 if (!mainHandler) {
59 auto runner = OHOS::AppExecFwk::EventRunner::GetMainEventRunner();
60 if (!runner) {
61 EDM_LOGE(MODULE_DEV_MGR, "get main event runner failed!");
62 return false;
63 }
64 mainHandler = std::make_shared<OHOS::AppExecFwk::EventHandler>(runner);
65 }
66 mainHandler->PostTask(func, "", 0, OHOS::AppExecFwk::EventQueue::Priority::HIGH, {});
67 EDM_LOGD(MODULE_DEV_MGR, "SendEventToMainThread end");
68 return true;
69 }
70
DeleteNapiRef()71 void AsyncData::DeleteNapiRef()
72 {
73 if (env == nullptr) {
74 return;
75 }
76 sptr<AsyncData> guard(this);
77
78 auto task = [guard]() {
79 EDM_LOGD(MODULE_DEV_MGR, "DeleteNapiRef async task is run.");
80
81 AsyncData* data = guard.GetRefPtr();
82 ani_env *taskEnv = nullptr;
83
84 bool attached = false;
85 ani_options aniArgs {0, nullptr};
86 if (ANI_ERROR == data->vm->AttachCurrentThread(&aniArgs, ANI_VERSION_1, &taskEnv)) {
87 if (ANI_OK != data->vm->GetEnv(ANI_VERSION_1, &taskEnv)) {
88 EDM_LOGE(MODULE_DEV_MGR, "GetEnv failed");
89 return;
90 }
91 } else {
92 attached = true;
93 }
94 if (data->onDisconnect != nullptr) {
95 taskEnv->GlobalReference_Delete(data->onDisconnect);
96 data->onDisconnect = nullptr;
97 }
98 if (attached) {
99 data->vm->DetachCurrentThread();
100 }
101 data->env = nullptr;
102 data->vm = nullptr;
103 };
104 if (!SendEventToMainThread(task)) {
105 EDM_LOGE(MODULE_DEV_MGR, "delete napi ref send event failed.");
106 guard = nullptr;
107 }
108 }
109
GetCallbackResult(ani_env * env,uint64_t deviceId,const sptr<IRemoteObject> & drvExtObj)110 static ani_object GetCallbackResult(ani_env *env, uint64_t deviceId, const sptr<IRemoteObject> &drvExtObj)
111 {
112 ani_long id = deviceId;
113 ani_ref remoteObj;
114 if (drvExtObj == nullptr) {
115 env->GetUndefined(&remoteObj);
116 EDM_LOGE(MODULE_DEV_MGR, "Remote obj is null.");
117 } else {
118 EDM_LOGI(MODULE_DEV_MGR, "Remote obj create.");
119 remoteObj = ANI_ohos_rpc_CreateJsRemoteObject(env, drvExtObj);
120 }
121
122 ani_object result {};
123 static const char *namespaceName = "L@ohos/driver/deviceManager/deviceManager;";
124 ani_namespace ns;
125 if (ANI_OK != env->FindNamespace(namespaceName, &ns)) {
126 EDM_LOGE(MODULE_DEV_MGR, "Not found '%{public}s'", namespaceName);
127 return result;
128 }
129
130 ani_class cls;
131 if (ANI_OK != env->Namespace_FindClass(ns, "LRemoteDeviceDriver_inner;", &cls)) {
132 EDM_LOGE(MODULE_DEV_MGR, "FindClass \"LRemoteDeviceDriver_inner;\" failed");
133 return result;
134 }
135
136 ani_method ctor;
137 if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", nullptr, &ctor)) {
138 EDM_LOGE(MODULE_DEV_MGR, "Class_FindMethod 'constructor' failed");
139 return result;
140 }
141
142 if (ANI_OK != env->Object_New(cls, ctor, &result, id, remoteObj)) {
143 EDM_LOGE(MODULE_DEV_MGR, "Object_New failed");
144 return result;
145 }
146 return result;
147 }
148
GetNapiError(int32_t errorCode)149 static std::optional<std::string> GetNapiError(int32_t errorCode)
150 {
151 auto iter = ERROR_MESSAGES.find(errorCode);
152 if (iter != ERROR_MESSAGES.end()) {
153 return iter->second;
154 }
155 return std::nullopt;
156 }
157
ConvertToBusinessError(ani_env * env,const ErrMsg & errMsg)158 static ani_object ConvertToBusinessError(ani_env *env, const ErrMsg &errMsg)
159 {
160 ani_ref businessError = nullptr;
161 if (errMsg.IsOk()) {
162 env->GetUndefined(&businessError);
163 return reinterpret_cast<ani_object>(businessError);
164 }
165
166 auto msgString = GetNapiError(SERVICE_EXCEPTION);
167 if (!msgString) {
168 env->GetUndefined(&businessError);
169 return reinterpret_cast<ani_object>(businessError);
170 }
171
172 ani_object errorObject = nullptr;
173 EDM_LOGD(MODULE_DEV_MGR, "Begin ThrowBusinessError.");
174 static const char *errorClsName = "L@ohos/base/BusinessError;";
175 ani_class cls {};
176 if (ANI_OK != env->FindClass(errorClsName, &cls)) {
177 EDM_LOGE(MODULE_DEV_MGR, "find class BusinessError %{public}s failed", errorClsName);
178 return errorObject;
179 }
180 ani_method ctor;
181 if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", ":V", &ctor)) {
182 EDM_LOGE(MODULE_DEV_MGR, "find method BusinessError.constructor failed");
183 return errorObject;
184 }
185
186 if (ANI_OK != env->Object_New(cls, ctor, &errorObject)) {
187 EDM_LOGE(MODULE_DEV_MGR, "create BusinessError object failed");
188 return errorObject;
189 }
190
191 ani_double aniErrCode = static_cast<ani_double>(SERVICE_EXCEPTION);
192 ani_string errMsgStr;
193 if (ANI_OK != env->String_NewUTF8(msgString->c_str(), msgString->size(), &errMsgStr)) {
194 EDM_LOGE(MODULE_DEV_MGR, "convert errMsg to ani_string failed");
195 return errorObject;
196 }
197 if (ANI_OK != env->Object_SetFieldByName_Double(errorObject, "code", aniErrCode)) {
198 EDM_LOGE(MODULE_DEV_MGR, "set error code failed");
199 return errorObject;
200 }
201 if (ANI_OK != env->Object_SetPropertyByName_Ref(errorObject, "message", errMsgStr)) {
202 EDM_LOGE(MODULE_DEV_MGR, "set error message failed");
203 return errorObject;
204 }
205
206 return errorObject;
207 }
208
ConvertToObjectDeviceId(ani_env * env,const uint64_t deviceId)209 static ani_object ConvertToObjectDeviceId(ani_env *env, const uint64_t deviceId)
210 {
211 ani_object retObject = nullptr;
212 ani_long aniDeviceId = deviceId;
213 ani_class cls {};
214 if (ANI_OK != env->FindClass("Lstd/core/Long;", &cls)) {
215 EDM_LOGE(MODULE_DEV_MGR, "find class Long Lstd/core/Long failed");
216 return retObject;
217 }
218 ani_method ctor;
219 if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", nullptr, &ctor)) {
220 EDM_LOGE(MODULE_DEV_MGR, "find method Long.constructor failed");
221 return retObject;
222 }
223 if (ANI_OK != env->Object_New(cls, ctor, &retObject, aniDeviceId)) {
224 EDM_LOGE(MODULE_DEV_MGR, "create Long object failed");
225 }
226 return retObject;
227 }
228
OnConnect(uint64_t deviceId,const sptr<IRemoteObject> & drvExtObj,const ErrMsg & errMsg)229 ErrCode DeviceManagerCallback::OnConnect(uint64_t deviceId, const sptr<IRemoteObject> &drvExtObj, const ErrMsg &errMsg)
230 {
231 EDM_LOGI(MODULE_DEV_MGR, "bind device callback: %{public}016" PRIX64, deviceId);
232 std::lock_guard<std::mutex> mapLock(mapMutex);
233 if (g_callbackMap.count(deviceId) == 0) {
234 EDM_LOGE(MODULE_DEV_MGR, "device OnConnect is null");
235 return EDM_NOK;
236 }
237
238 auto data = g_callbackMap[deviceId];
239 if (!errMsg.IsOk()) {
240 g_callbackMap.erase(deviceId);
241 }
242 auto task = [data, drvExtObj, errMsg]() {
243 EDM_LOGE(MODULE_DEV_MGR, "OnConnect async task is run.");
244 ani_env *env = nullptr;
245 ani_options aniArgs {0, nullptr};
246 int32_t ret = data->vm->AttachCurrentThread(&aniArgs, ANI_VERSION_1, &env);
247 if (ANI_ERROR == ret) {
248 if (ANI_OK != data->vm->GetEnv(ANI_VERSION_1, &env)) {
249 EDM_LOGE(MODULE_DEV_MGR, "GetEnv failed");
250 }
251 }
252 if (ANI_OK != env->CreateLocalScope(ANI_SCOPE_SIZE)) {
253 EDM_LOGE(MODULE_DEV_MGR, "CreateLocalScope failed");
254 if (ret == ANI_OK) {
255 data->vm->DetachCurrentThread();
256 }
257 }
258 ani_object result = GetCallbackResult(env, data->deviceId, drvExtObj);
259 ani_object err = ConvertToBusinessError(env, errMsg);
260 if (data->bindDeferred != nullptr) {
261 if (errMsg.IsOk()) {
262 env->PromiseResolver_Resolve(data->bindDeferred, result);
263 } else {
264 env->PromiseResolver_Reject(data->bindDeferred, reinterpret_cast<ani_error>(err));
265 }
266 EDM_LOGD(MODULE_DEV_MGR, "bind device promise finish.");
267 }
268 env->DestroyLocalScope();
269 if (ret == ANI_OK) {
270 data->vm->DetachCurrentThread();
271 }
272 };
273 if (!SendEventToMainThread(task)) {
274 EDM_LOGE(MODULE_DEV_MGR, "OnConnect send event failed.");
275 return EDM_NOK;
276 }
277 return EDM_OK;
278 }
279
OnDisconnect(uint64_t deviceId,const ErrMsg & errMsg)280 ErrCode DeviceManagerCallback::OnDisconnect(uint64_t deviceId, const ErrMsg &errMsg)
281 {
282 EDM_LOGI(MODULE_DEV_MGR, "device onDisconnect: %{public}016" PRIX64, deviceId);
283 std::lock_guard<std::mutex> mapLock(mapMutex);
284 if (g_callbackMap.count(deviceId) == 0) {
285 EDM_LOGE(MODULE_DEV_MGR, "device callback map is null");
286 return EDM_NOK;
287 }
288
289 auto data = g_callbackMap[deviceId];
290 g_callbackMap.erase(deviceId);
291 if (data->onDisconnect == nullptr) {
292 EDM_LOGE(MODULE_DEV_MGR, "device callback is null");
293 return EDM_NOK;
294 }
295 data->IncStrongRef(nullptr);
296 auto task = [data, errMsg]() {
297 EDM_LOGD(MODULE_DEV_MGR, "OnDisconnect async task is run.");
298 ani_env *env = nullptr;
299 ani_options aniArgs {0, nullptr};
300 int32_t ret = data->vm->AttachCurrentThread(&aniArgs, ANI_VERSION_1, &env);
301 if (ret != ANI_OK && data->vm->GetEnv(ANI_VERSION_1, &env) != ANI_OK) {
302 EDM_LOGE(MODULE_DEV_MGR, "Failed to get JNI environment.");
303 data->DecStrongRef(nullptr);
304 }
305 if (ANI_OK != env->CreateLocalScope(ANI_SCOPE_SIZE)) {
306 EDM_LOGE(MODULE_DEV_MGR, "Failed to create local scope.");
307 data->DecStrongRef(nullptr);
308 if (ret == ANI_OK) {
309 data->vm->DetachCurrentThread();
310 }
311 }
312 ani_ref argv[] = {ConvertToBusinessError(env, errMsg), ConvertToObjectDeviceId(env, data->deviceId)};
313 ani_ref result;
314 auto fnObj = reinterpret_cast<ani_fn_object>(data->onDisconnect);
315 auto callRet = env->FunctionalObject_Call(fnObj, TWO_PARAMETERS, argv, &result);
316 EDM_LOGD(MODULE_DEV_MGR, "OnDisconnect callback finish ret: %{public}u", callRet);
317 env->DestroyLocalScope();
318 data->DecStrongRef(nullptr);
319 if (ret == ANI_OK) {
320 data->vm->DetachCurrentThread();
321 }
322 };
323 if (!SendEventToMainThread(task)) {
324 EDM_LOGE(MODULE_DEV_MGR, "OnDisconnect send event failed.");
325 data->DecStrongRef(nullptr);
326 return EDM_NOK;
327 }
328 return EDM_OK;
329 }
330
OnUnBind(uint64_t deviceId,const ErrMsg & errMsg)331 ErrCode DeviceManagerCallback::OnUnBind(uint64_t deviceId, const ErrMsg &errMsg)
332 {
333 EDM_LOGI(MODULE_DEV_MGR, "unbind device callback: %{public}016" PRIX64, deviceId);
334 std::lock_guard<std::mutex> mapLock(mapMutex);
335 if (g_callbackMap.count(deviceId) == 0) {
336 EDM_LOGE(MODULE_DEV_MGR, "device unbind map is null");
337 return EDM_NOK;
338 }
339
340 auto asyncData = g_callbackMap[deviceId];
341 if (asyncData == nullptr) {
342 EDM_LOGE(MODULE_DEV_MGR, "device unbind is null");
343 return EDM_NOK;
344 }
345 asyncData->unBindErrMsg = errMsg;
346 return EDM_OK;
347 }
348
ConvertToDevice(std::shared_ptr<DeviceData> & deviceData)349 static ohos::driver::deviceManager::DeviceUnion ConvertToDevice(std::shared_ptr<DeviceData> &deviceData)
350 {
351 if (deviceData->busType == OHOS::ExternalDeviceManager::BusType::BUS_TYPE_USB) {
352 std::shared_ptr<OHOS::ExternalDeviceManager::USBDevice> usb =
353 std::static_pointer_cast<OHOS::ExternalDeviceManager::USBDevice>(deviceData);
354 auto taiheUsbDevice = ohos::driver::deviceManager::USBDevice{
355 {
356 std::move(ohos::driver::deviceManager::BusType::key_t::USB),
357 std::move(deviceData->deviceId),
358 std::move(deviceData->descripton)
359 },
360 std::move(usb->vendorId),
361 std::move(usb->productId)
362 };
363 return ohos::driver::deviceManager::DeviceUnion(
364 ::taihe::static_tag<::ohos::driver::deviceManager::DeviceUnion::tag_t::t1>, taiheUsbDevice);
365 } else {
366 auto taiheDevice = ohos::driver::deviceManager::Device{
367 std::move(ohos::driver::deviceManager::BusType::key_t::USB),
368 std::move(deviceData->deviceId),
369 std::move(deviceData->descripton)
370 };
371 return ohos::driver::deviceManager::DeviceUnion(
372 ::taihe::static_tag<::ohos::driver::deviceManager::DeviceUnion::tag_t::t>, taiheDevice);
373 }
374 }
queryDevices(optional_view<int32_t> busType)375 array<ohos::driver::deviceManager::DeviceUnion> queryDevices(optional_view<int32_t> busType)
376 {
377 EDM_LOGI(MODULE_DEV_MGR, "queryDevices start");
378 bool isBusTypeSet = busType.has_value();
379 int32_t busTypeVal = isBusTypeSet ? busType.value() : OHOS::ExternalDeviceManager::BusType::BUS_TYPE_USB;
380 EDM_LOGI(MODULE_DEV_MGR, "bus type is %{public}d", busTypeVal);
381 std::vector<std::shared_ptr<DeviceData>> devices;
382 std::vector<ohos::driver::deviceManager::DeviceUnion> resultArray;
383 UsbErrCode retCode = g_edmClient.QueryDevice(busTypeVal, devices);
384 if (retCode != UsbErrCode::EDM_OK) {
385 if (retCode == UsbErrCode::EDM_ERR_NO_PERM) {
386 set_business_error(PERMISSION_DENIED, "queryDevice: no permission");
387 } else {
388 EDM_LOGD(MODULE_DEV_MGR, "queryDevices error code: %{public}d", retCode);
389 set_business_error(SERVICE_EXCEPTION, "Query device service fail");
390 }
391 return array<ohos::driver::deviceManager::DeviceUnion>(resultArray);
392 }
393 for (auto &deviceItem : devices) {
394 resultArray.push_back(ConvertToDevice(deviceItem));
395 }
396 EDM_LOGI(MODULE_DEV_MGR, "query device finish");
397 return array<ohos::driver::deviceManager::DeviceUnion>(resultArray);
398 }
399
ParseToUSBInterfaceDesc(std::shared_ptr<OHOS::ExternalDeviceManager::USBInterfaceDesc> & usbInterfaceDesc)400 static ohos::driver::deviceManager::USBInterfaceDesc ParseToUSBInterfaceDesc(
401 std::shared_ptr<OHOS::ExternalDeviceManager::USBInterfaceDesc> &usbInterfaceDesc)
402 {
403 return {
404 .bInterfaceNumber = usbInterfaceDesc->bInterfaceNumber,
405 .bClass = usbInterfaceDesc->bClass,
406 .bSubClass = usbInterfaceDesc->bSubClass,
407 .bProtocol = usbInterfaceDesc->bProtocol,
408 };
409 }
410
ConvertToDeviceInfo(std::shared_ptr<DeviceInfoData> & deviceInfoData)411 static ohos::driver::deviceManager::DeviceInfoUnion ConvertToDeviceInfo(std::shared_ptr<DeviceInfoData> &deviceInfoData)
412 {
413 EDM_LOGD(MODULE_DEV_MGR, "ConvertToDeviceInfo start");
414 auto busType = DeviceInfoData::GetBusTypeByDeviceId(deviceInfoData->deviceId);
415 if (busType == OHOS::ExternalDeviceManager::BusType::BUS_TYPE_USB) {
416 std::shared_ptr<USBDeviceInfoData> usbDeviceInfo = std::static_pointer_cast<USBDeviceInfoData>(deviceInfoData);
417 optional<string> driverUid;
418 if (deviceInfoData->isDriverMatched) {
419 driverUid = optional<string>(std::in_place, deviceInfoData->driverUid);
420 } else {
421 driverUid = optional<string>(std::nullopt);
422 }
423 std::vector<ohos::driver::deviceManager::USBInterfaceDesc> taiheInterfaceDesc;
424 for (auto &interfaceDesc : usbDeviceInfo->interfaceDescList) {
425 taiheInterfaceDesc.push_back(ParseToUSBInterfaceDesc(interfaceDesc));
426 }
427 array<::ohos::driver::deviceManager::USBInterfaceDesc> structDescList(taiheInterfaceDesc);
428 auto taiheDeviceInfoData = ohos::driver::deviceManager::USBDeviceInfo{
429 {
430 std::move(deviceInfoData->deviceId),
431 std::move(deviceInfoData->isDriverMatched),
432 std::move(driverUid),
433 },
434 std::move(usbDeviceInfo->vendorId),
435 std::move(usbDeviceInfo->productId),
436 std::move(structDescList),
437 };
438 return ohos::driver::deviceManager::DeviceInfoUnion(
439 ::taihe::static_tag<::ohos::driver::deviceManager::DeviceInfoUnion::tag_t::t1>, taiheDeviceInfoData);
440 } else {
441 auto driverUid = deviceInfoData->driverUid.empty() ? optional<string>(std::nullopt) :
442 optional<string>(std::in_place_t{}, deviceInfoData->driverUid);
443 auto taiheDeviceInfoData = ohos::driver::deviceManager::DeviceInfo{
444 std::move(deviceInfoData->deviceId),
445 std::move(deviceInfoData->isDriverMatched),
446 std::move(driverUid)
447 };
448 return ohos::driver::deviceManager::DeviceInfoUnion(
449 ::taihe::static_tag<::ohos::driver::deviceManager::DeviceInfoUnion::tag_t::t>, taiheDeviceInfoData);
450 }
451 }
452
queryDeviceInfo(optional_view<uint64_t> deviceId)453 array<ohos::driver::deviceManager::DeviceInfoUnion> queryDeviceInfo(optional_view<uint64_t> deviceId)
454 {
455 EDM_LOGD(MODULE_DEV_MGR, "queryDeviceInfo start");
456 std::vector<std::shared_ptr<DeviceInfoData>> deviceInfos;
457 int32_t ret;
458 bool isDeviceIdSet = deviceId.has_value();
459 if (isDeviceIdSet) {
460 ret = g_edmClient.QueryDeviceInfo(deviceId.value(), deviceInfos);
461 } else {
462 ret = g_edmClient.QueryDeviceInfo(deviceInfos);
463 }
464 std::vector<ohos::driver::deviceManager::DeviceInfoUnion> resultArray;
465 if (ret != UsbErrCode::EDM_OK) {
466 if (ret == UsbErrCode::EDM_ERR_NOT_SYSTEM_APP) {
467 set_business_error(PERMISSION_NOT_SYSTEM_APP, "queryDeviceInfo: none system app");
468 } else if (ret == UsbErrCode::EDM_ERR_NO_PERM) {
469 set_business_error(PERMISSION_DENIED, "queryDeviceInfo: no permission");
470 } else {
471 set_business_error(SERVICE_EXCEPTION_NEW, "Query device info service fail");
472 }
473 return array<ohos::driver::deviceManager::DeviceInfoUnion>(resultArray);
474 }
475
476 for (auto &deviceInfoItem : deviceInfos) {
477 resultArray.push_back(ConvertToDeviceInfo(deviceInfoItem));
478 }
479
480 return array<ohos::driver::deviceManager::DeviceInfoUnion>(resultArray);
481 }
482
ConvertToDriverInfo(std::shared_ptr<DriverInfoData> & driverInfoData)483 static ohos::driver::deviceManager::DriverInfoUnion ConvertToDriverInfo(std::shared_ptr<DriverInfoData> &driverInfoData)
484 {
485 EDM_LOGD(MODULE_DEV_MGR, "ConvertToDriverInfo start");
486 if (driverInfoData->busType == OHOS::ExternalDeviceManager::BusType::BUS_TYPE_USB) {
487 std::shared_ptr<USBDriverInfoData> usbDriverInfo = std::static_pointer_cast<USBDriverInfoData>(driverInfoData);
488
489 std::vector<int32_t> pids;
490 for (auto pidItem : usbDriverInfo->pids) {
491 pids.push_back(pidItem);
492 }
493 array<int32_t> pidList(pids);
494
495 std::vector<int32_t> vids;
496 for (auto vidItem : usbDriverInfo->vids) {
497 vids.push_back(vidItem);
498 }
499 array<int32_t> vidList(vids);
500
501 auto taiheUSBDriverInfoData = ohos::driver::deviceManager::USBDriverInfo{
502 {
503 std::move(ohos::driver::deviceManager::BusType::key_t::USB),
504 std::move(driverInfoData->driverUid),
505 std::move(driverInfoData->driverName),
506 std::move(driverInfoData->version),
507 std::move(driverInfoData->bundleSize),
508 std::move(driverInfoData->description),
509 },
510 std::move(pidList),
511 std::move(vidList),
512 };
513 return ohos::driver::deviceManager::DriverInfoUnion(
514 ::taihe::static_tag<::ohos::driver::deviceManager::DriverInfoUnion::tag_t::t1>, taiheUSBDriverInfoData);
515 } else {
516 auto taiheDriverInfoData = ohos::driver::deviceManager::DriverInfo{
517 std::move(ohos::driver::deviceManager::BusType::key_t::USB),
518 std::move(driverInfoData->driverUid),
519 std::move(driverInfoData->driverName),
520 std::move(driverInfoData->version),
521 std::move(driverInfoData->bundleSize),
522 std::move(driverInfoData->description),
523 };
524 return ohos::driver::deviceManager::DriverInfoUnion(
525 ::taihe::static_tag<::ohos::driver::deviceManager::DriverInfoUnion::tag_t::t>, taiheDriverInfoData);
526 }
527 }
528
queryDriverInfo(optional_view<string> driverUid)529 array<ohos::driver::deviceManager::DriverInfoUnion> queryDriverInfo(optional_view<string> driverUid)
530 {
531 EDM_LOGD(MODULE_DEV_MGR, "queryDriverInfo start");
532 std::vector<std::shared_ptr<DriverInfoData>> driverInfos;
533 std::vector<ohos::driver::deviceManager::DriverInfoUnion> resultArray;
534 int32_t ret;
535 bool isDriverUidSet = driverUid.has_value();
536 if (isDriverUidSet) {
537 ret = g_edmClient.QueryDriverInfo(driverUid.value().c_str(), driverInfos);
538 } else {
539 ret = g_edmClient.QueryDriverInfo(driverInfos);
540 }
541
542 if (ret != UsbErrCode::EDM_OK) {
543 if (ret == UsbErrCode::EDM_ERR_NOT_SYSTEM_APP) {
544 set_business_error(PERMISSION_NOT_SYSTEM_APP, "queryDriverInfo: none system app");
545 } else if (ret == UsbErrCode::EDM_ERR_NO_PERM) {
546 set_business_error(PERMISSION_DENIED, "queryDriverInfo: no permission");
547 } else {
548 set_business_error(SERVICE_EXCEPTION_NEW, "Query driver info service fail");
549 }
550 return array<ohos::driver::deviceManager::DriverInfoUnion>(resultArray);
551 }
552
553 for (auto &driverInfoItem : driverInfos) {
554 resultArray.push_back(ConvertToDriverInfo(driverInfoItem));
555 }
556 return array<ohos::driver::deviceManager::DriverInfoUnion>(resultArray);
557 }
558
BindDriverWithDeviceIdSync(ani_env * env,ani_long deviceId,ani_object onDisconnect)559 ani_object BindDriverWithDeviceIdSync([[maybe_unused]] ani_env *env, ani_long deviceId, ani_object onDisconnect)
560 {
561 EDM_LOGI(MODULE_DEV_MGR, "Enter BindDriverWithDeviceIdSync:%{public}016" PRIX64, static_cast<uint64_t>(deviceId));
562 std::lock_guard<std::mutex> mapLock(mapMutex);
563 UsbErrCode retCode = g_edmClient.BindDriverWithDeviceId(deviceId, g_edmCallback);
564 if (retCode != UsbErrCode::EDM_OK) {
565 if (retCode == UsbErrCode::EDM_ERR_NO_PERM) {
566 set_business_error(PERMISSION_DENIED, "bindDevice: no permission");
567 } else if (retCode == UsbErrCode::EDM_ERR_SERVICE_NOT_ALLOW_ACCESS) {
568 set_business_error(SERVICE_NOT_ALLOW_ACCESS, "bindDevice: service not allowed");
569 } else {
570 set_business_error(SERVICE_EXCEPTION_NEW, "bindDevice service failed");
571 }
572 return nullptr;
573 }
574
575 ani_vm *vm = nullptr;
576 if (ANI_OK != env->GetVM(&vm)) {
577 EDM_LOGE(MODULE_DEV_MGR, "GetVM failed.");
578 return nullptr;
579 }
580 sptr<AsyncData> data = new (std::nothrow) AsyncData(vm, env);
581 if (data == nullptr) {
582 set_business_error(PARAMETER_ERROR, "malloc callback data fail");
583 return nullptr;
584 }
585
586 data->env = env;
587 data->deviceId = deviceId;
588 if (ANI_OK != env->GlobalReference_Create(reinterpret_cast<ani_ref>(onDisconnect), &data->onDisconnect)) {
589 set_business_error(PARAMETER_ERROR, "GlobalReference_Create failed");
590 return nullptr;
591 }
592
593 ani_object promise;
594 env->Promise_New(&data->bindDeferred, &promise);
595 g_callbackMap[data->deviceId] = data;
596 return promise;
597 }
598
UnbindDriverWithDeviceIdSync(uint64_t deviceId)599 int32_t UnbindDriverWithDeviceIdSync(uint64_t deviceId)
600 {
601 EDM_LOGI(MODULE_DEV_MGR, "Enter unbindDevice:%{public}016" PRIX64, deviceId);
602 UsbErrCode retCode = g_edmClient.UnbindDriverWithDeviceId(deviceId);
603 if (retCode != UsbErrCode::EDM_OK) {
604 if (retCode == UsbErrCode::EDM_ERR_NO_PERM) {
605 set_business_error(PERMISSION_DENIED, "unbindDevice: no permission");
606 } else if (retCode == UsbErrCode::EDM_ERR_SERVICE_NOT_BOUND) {
607 set_business_error(SERVICE_NOT_BOUND, "unbindDevice: there is no binding relationship");
608 } else {
609 set_business_error(SERVICE_EXCEPTION_NEW, "unbindDevice service failed");
610 }
611 }
612 return retCode;
613 }
614 }
615 } // namespace
616
617 // Since these macros are auto-generate, lint will cause false positive.
618 // NOLINTBEGIN
619 TH_EXPORT_CPP_API_queryDevices(OHOS::ExternalDeviceManager::queryDevices);
620 TH_EXPORT_CPP_API_queryDeviceInfo(OHOS::ExternalDeviceManager::queryDeviceInfo);
621 TH_EXPORT_CPP_API_queryDriverInfo(OHOS::ExternalDeviceManager::queryDriverInfo);
622 TH_EXPORT_CPP_API_UnbindDriverWithDeviceIdSync(OHOS::ExternalDeviceManager::UnbindDriverWithDeviceIdSync);
623 // NOLINTEND
624