• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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