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
16 #include "etx_device_mgr.h"
17 #include "cinttypes"
18 #include "common_timer_errors.h"
19 #include "driver_extension_controller.h"
20 #include "driver_pkg_manager.h"
21 #include "edm_errors.h"
22 #include "hilog_wrapper.h"
23 #include "iservice_registry.h"
24 #include "system_ability_definition.h"
25
26 namespace OHOS {
27 namespace ExternalDeviceManager {
28 constexpr uint32_t UNLOAD_SA_TIMER_INTERVAL = 30 * 1000;
29 std::string Device::stiching_ = "_stiching_";
30 IMPLEMENT_SINGLE_INSTANCE(ExtDeviceManager);
31
~ExtDeviceManager()32 ExtDeviceManager::~ExtDeviceManager()
33 {
34 unloadSelftimer_.Unregister(unloadSelftimerId_);
35 unloadSelftimer_.Shutdown();
36 }
37
PrintMatchDriverMap()38 void ExtDeviceManager::PrintMatchDriverMap()
39 {
40 if (!bundleMatchMap_.empty()) {
41 EDM_LOGD(MODULE_DEV_MGR, " bundleInfo map size[%{public}zu]", bundleMatchMap_.size());
42 for (auto iter : bundleMatchMap_) {
43 for (auto iterId = iter.second.begin(); iterId != iter.second.end(); ++iterId) {
44 uint64_t deviceId = *iterId;
45 EDM_LOGD(MODULE_DEV_MGR, "print match map info[%{public}s], deviceId %{public}016" PRIX64 "",
46 iter.first.c_str(), deviceId);
47 }
48 }
49 EDM_LOGD(MODULE_DEV_MGR, "ExtDeviceManager print driver match map success");
50 }
51 }
52
Init()53 int32_t ExtDeviceManager::Init()
54 {
55 EDM_LOGD(MODULE_DEV_MGR, "ExtDeviceManager Init success");
56 int32_t ret = DriverPkgManager::GetInstance().RegisterOnBundleUpdate(UpdateBundleStatusCallback);
57 if (ret != EDM_OK) {
58 EDM_LOGE(MODULE_DEV_MGR, "register bundle status callback fail");
59 return EDM_NOK;
60 }
61 return EDM_OK;
62 }
63
AddDevIdOfBundleInfoMap(shared_ptr<Device> device,string & bundleInfo)64 int32_t ExtDeviceManager::AddDevIdOfBundleInfoMap(shared_ptr<Device> device, string &bundleInfo)
65 {
66 if (bundleInfo.empty() || device == nullptr) {
67 EDM_LOGE(MODULE_DEV_MGR, "bundleInfo or device is null");
68 return EDM_ERR_INVALID_PARAM;
69 }
70
71 // update bundle info
72 lock_guard<mutex> lock(bundleMatchMapMutex_);
73 auto pos = bundleMatchMap_.find(bundleInfo);
74 uint64_t deviceId = device->GetDeviceInfo()->GetDeviceId();
75 if (pos == bundleMatchMap_.end()) {
76 unordered_set<uint64_t> tmpSet;
77 tmpSet.emplace(deviceId);
78 bundleMatchMap_.emplace(bundleInfo, tmpSet);
79 EDM_LOGI(MODULE_DEV_MGR, "bundleMap emplace New driver, add deviceId %{public}016" PRIX64 "", deviceId);
80 } else {
81 auto pairRet = pos->second.emplace(deviceId);
82 // Check whether the deviceId matches the driver
83 if (!pairRet.second || pos->second.size() > 1) {
84 EDM_LOGI(MODULE_DEV_MGR, "bundleMap had existed driver, add deviceId %{public}016" PRIX64 "", deviceId);
85 PrintMatchDriverMap();
86 }
87 }
88
89 // start ability
90 int32_t ret = device->Connect();
91 if (ret != EDM_OK) {
92 EDM_LOGE(MODULE_DEV_MGR,
93 "deviceId[%{public}016" PRIX64 "] connect driver extension ability[%{public}s] failed[%{public}d]",
94 deviceId, Device::GetAbilityName(bundleInfo).c_str(), ret);
95 return EDM_NOK;
96 }
97 PrintMatchDriverMap();
98 return EDM_OK;
99 }
100
RemoveDevIdOfBundleInfoMap(shared_ptr<Device> device,string & bundleInfo)101 int32_t ExtDeviceManager::RemoveDevIdOfBundleInfoMap(shared_ptr<Device> device, string &bundleInfo)
102 {
103 if (bundleInfo.empty() || device == nullptr) {
104 EDM_LOGE(MODULE_DEV_MGR, "bundleInfo or device is null");
105 return EDM_ERR_INVALID_PARAM;
106 }
107
108 // update bundle info
109 lock_guard<mutex> lock(bundleMatchMapMutex_);
110 auto pos = bundleMatchMap_.find(bundleInfo);
111 if (pos == bundleMatchMap_.end()) {
112 EDM_LOGI(MODULE_DEV_MGR, "not find bundleInfo from map");
113 return EDM_OK;
114 }
115
116 // If the number of devices is greater than one, only the device erase
117 uint64_t deviceId = device->GetDeviceInfo()->GetDeviceId();
118 if (pos->second.size() > 1) {
119 pos->second.erase(deviceId);
120 EDM_LOGD(MODULE_DEV_MGR, "bundleMap existed driver, remove deviceId %{public}016" PRIX64 "", deviceId);
121 PrintMatchDriverMap();
122 return EDM_OK;
123 }
124
125 EDM_LOGD(MODULE_DEV_MGR, "bundleMap remove bundleInfo[%{public}s]", bundleInfo.c_str());
126 bundleMatchMap_.erase(pos);
127
128 // stop ability and destory sa
129 int32_t ret = device->Disconnect();
130 if (ret != EDM_OK) {
131 EDM_LOGE(MODULE_DEV_MGR,
132 "deviceId[%{public}016" PRIX64 "] disconnect driver extension ability[%{public}s] failed[%{public}d]",
133 deviceId, Device::GetAbilityName(bundleInfo).c_str(), ret);
134 return ret;
135 }
136 PrintMatchDriverMap();
137 return EDM_OK;
138 }
139
RemoveAllDevIdOfBundleInfoMap(shared_ptr<Device> device,string & bundleInfo)140 int32_t ExtDeviceManager::RemoveAllDevIdOfBundleInfoMap(shared_ptr<Device> device, string &bundleInfo)
141 {
142 if (device == nullptr) {
143 EDM_LOGE(MODULE_DEV_MGR, "device is null");
144 return EDM_ERR_INVALID_PARAM;
145 }
146 // update bundle info
147 lock_guard<mutex> lock(bundleMatchMapMutex_);
148 auto pos = bundleMatchMap_.find(bundleInfo);
149 if (pos == bundleMatchMap_.end()) {
150 return EDM_OK;
151 }
152
153 bundleMatchMap_.erase(pos);
154 // stop ability and destory sa
155 int32_t ret = device->Disconnect();
156 if (ret != EDM_OK) {
157 EDM_LOGE(MODULE_DEV_MGR, "disconnect driver extension ability[%{public}s] failed[%{public}d]",
158 Device::GetAbilityName(bundleInfo).c_str(), ret);
159 return ret;
160 }
161 return EDM_OK;
162 }
163
AddBundleInfo(enum BusType busType,const string & bundleName,const string & abilityName)164 int32_t ExtDeviceManager::AddBundleInfo(enum BusType busType, const string &bundleName, const string &abilityName)
165 {
166 EDM_LOGI(MODULE_DEV_MGR, "%{public}s enter", __func__);
167 if (busType <= BUS_TYPE_INVALID || busType > BUS_TYPE_TEST) {
168 EDM_LOGE(MODULE_DEV_MGR, "busType para invalid");
169 return EDM_ERR_INVALID_PARAM;
170 }
171
172 if (bundleName.empty() || abilityName.empty()) {
173 EDM_LOGE(MODULE_DEV_MGR, "BundleInfo para invalid");
174 return EDM_ERR_INVALID_PARAM;
175 }
176
177 // iterate over device, find bundleInfo and ability status
178 lock_guard<mutex> lock(deviceMapMutex_);
179
180 // find device
181 if (deviceMap_.count(busType) == 0) {
182 EDM_LOGD(MODULE_DEV_MGR, "deviceMap_ not bustype[%{public}d], wait to plug device", busType);
183 return EDM_OK;
184 }
185
186 string bundleInfo = bundleName + Device::GetStiching() + abilityName;
187 unordered_map<uint64_t, shared_ptr<Device>> &map = deviceMap_[busType];
188
189 for (auto iter : map) {
190 shared_ptr<Device> device = iter.second;
191
192 // iterate over device by bustype
193 auto bundleInfoNames = DriverPkgManager::GetInstance().QueryMatchDriver(device->GetDeviceInfo());
194 if (bundleInfoNames == nullptr) {
195 EDM_LOGD(MODULE_DEV_MGR, "deviceId[%{public}016" PRIX64 "], not find driver",
196 device->GetDeviceInfo()->GetDeviceId());
197 continue;
198 }
199
200 if (bundleName.compare(bundleInfoNames->bundleName) == 0 &&
201 abilityName.compare(bundleInfoNames->abilityName) == 0) {
202 device->AddBundleInfo(bundleInfo);
203 int32_t ret = AddDevIdOfBundleInfoMap(device, bundleInfo);
204 if (ret != EDM_OK) {
205 EDM_LOGE(MODULE_DEV_MGR,
206 "deviceId[%{public}016" PRIX64 "] start driver extension ability[%{public}s] fail[%{public}d]",
207 device->GetDeviceInfo()->GetDeviceId(), Device::GetAbilityName(bundleInfo).c_str(), ret);
208 }
209 }
210 }
211
212 return EDM_OK;
213 }
214
RemoveBundleInfo(enum BusType busType,const string & bundleName,const string & abilityName)215 int32_t ExtDeviceManager::RemoveBundleInfo(enum BusType busType, const string &bundleName, const string &abilityName)
216 {
217 EDM_LOGI(MODULE_DEV_MGR, "%{public}s enter", __func__);
218 if (busType <= BUS_TYPE_INVALID || busType >= BUS_TYPE_TEST) {
219 EDM_LOGE(MODULE_DEV_MGR, "busType para invalid");
220 return EDM_ERR_INVALID_PARAM;
221 }
222
223 if (bundleName.empty() || abilityName.empty()) {
224 EDM_LOGE(MODULE_DEV_MGR, "BundleInfo para invalid");
225 return EDM_ERR_INVALID_PARAM;
226 }
227
228 lock_guard<mutex> lock(deviceMapMutex_);
229 if (deviceMap_.count(busType) == 0) {
230 EDM_LOGD(MODULE_DEV_MGR, "deviceMap_ not bustype[%{public}d], wait to plug device", busType);
231 return EDM_OK;
232 }
233
234 // iterate over device, remove bundleInfo
235 string bundleInfo = bundleName + Device::GetStiching() + abilityName;
236 unordered_map<uint64_t, shared_ptr<Device>> &deviceMap = deviceMap_[busType];
237
238 for (auto iter : deviceMap) {
239 shared_ptr<Device> device = iter.second;
240
241 // iterate over device by bustype
242 if (bundleInfo.compare(device->GetBundleInfo()) == 0) {
243 int32_t ret = RemoveAllDevIdOfBundleInfoMap(device, bundleInfo);
244 device->RemoveBundleInfo(); // update device
245 if (ret != EDM_OK) {
246 EDM_LOGE(MODULE_DEV_MGR,
247 "deviceId[%{public}016" PRIX64 "] stop driver extension ability[%{public}s] fail[%{public}d]",
248 device->GetDeviceInfo()->GetDeviceId(), Device::GetAbilityName(bundleInfo).c_str(), ret);
249 }
250 }
251 }
252 return EDM_OK;
253 }
254
UpdateBundleInfo(enum BusType busType,const string & bundleName,const string & abilityName)255 int32_t ExtDeviceManager::UpdateBundleInfo(enum BusType busType, const string &bundleName, const string &abilityName)
256 {
257 EDM_LOGI(MODULE_DEV_MGR, "%{public}s enter", __func__);
258 // stop ability of device and reset bundleInfo of device
259 int32_t ret = RemoveBundleInfo(busType, bundleName, abilityName);
260 if (ret != EDM_OK) {
261 EDM_LOGE(MODULE_DEV_MGR, "remove bundle info fail");
262 return EDM_NOK;
263 }
264
265 // iterate over device, add bundleInfo and start ability
266 ret = AddBundleInfo(busType, bundleName, abilityName);
267 if (ret != EDM_OK) {
268 EDM_LOGE(MODULE_DEV_MGR, "add bundle info fail");
269 return EDM_NOK;
270 }
271
272 return EDM_OK;
273 }
274
UpdateBundleStatusCallback(int32_t bundleStatus,int32_t busType,const string & bundleName,const string & abilityName)275 int32_t ExtDeviceManager::UpdateBundleStatusCallback(
276 int32_t bundleStatus, int32_t busType, const string &bundleName, const string &abilityName)
277 {
278 int32_t ret = EDM_NOK;
279 if (bundleStatus < BUNDLE_ADDED || bundleStatus > BUNDLE_REMOVED) {
280 EDM_LOGE(MODULE_DEV_MGR, "bundleStatus para invalid");
281 return EDM_ERR_INVALID_PARAM;
282 }
283
284 // add bundle
285 if (bundleStatus == BUNDLE_ADDED) {
286 ret = ExtDeviceManager::GetInstance().AddBundleInfo((enum BusType)busType, bundleName, abilityName);
287 if (ret != EDM_OK) {
288 EDM_LOGE(MODULE_DEV_MGR, "callback add bundle info fail");
289 }
290 return ret;
291 }
292
293 // update bundle
294 if (bundleStatus == BUNDLE_UPDATED) {
295 ret = ExtDeviceManager::GetInstance().UpdateBundleInfo((enum BusType)busType, bundleName, abilityName);
296 if (ret != EDM_OK) {
297 EDM_LOGE(MODULE_DEV_MGR, "callback update bundle info fail");
298 }
299 return ret;
300 }
301
302 // remove bundle
303 ret = ExtDeviceManager::GetInstance().RemoveBundleInfo((enum BusType)busType, bundleName, abilityName);
304 if (ret != EDM_OK) {
305 EDM_LOGE(MODULE_DEV_MGR, "callback remove bundle info fail");
306 }
307
308 return ret;
309 }
310
RegisterDevice(shared_ptr<DeviceInfo> devInfo)311 int32_t ExtDeviceManager::RegisterDevice(shared_ptr<DeviceInfo> devInfo)
312 {
313 BusType type = devInfo->GetBusType();
314 uint64_t deviceId = devInfo->GetDeviceId();
315 shared_ptr<Device> device;
316 lock_guard<mutex> lock(deviceMapMutex_);
317 if (deviceMap_.find(type) != deviceMap_.end()) {
318 unordered_map<uint64_t, shared_ptr<Device>> &map = deviceMap_[type];
319 if (map.find(deviceId) != map.end()) {
320 device = map.find(deviceId)->second;
321 // device has been registered and do not need to connect again
322 if (device->GetDrvExtRemote() != nullptr) {
323 EDM_LOGI(MODULE_DEV_MGR, "device has been registered, deviceId is %{public}016" PRIx64 "", deviceId);
324 return EDM_OK;
325 }
326 // device has been registered and need to connect
327 EDM_LOGI(MODULE_DEV_MGR, "device has been registered, deviceId is %{public}016" PRIx64 "", deviceId);
328 }
329 }
330 EDM_LOGD(MODULE_DEV_MGR, "begin to register device, deviceId is %{public}016" PRIx64 "", deviceId);
331 // device need to register
332 if (device == nullptr) {
333 device = make_shared<Device>(devInfo);
334 deviceMap_[type].emplace(deviceId, device);
335 EDM_LOGI(MODULE_DEV_MGR, "successfully registered device, deviceId = %{public}016" PRIx64 "", deviceId);
336 }
337 // driver match
338 std::string bundleInfo = device->GetBundleInfo();
339 // if device does not have a matching driver, match driver here
340 if (bundleInfo.empty()) {
341 auto bundleInfoNames = DriverPkgManager::GetInstance().QueryMatchDriver(devInfo);
342 if (bundleInfoNames != nullptr) {
343 bundleInfo = bundleInfoNames->bundleName + Device::GetStiching() + bundleInfoNames->abilityName;
344 device->AddBundleInfo(bundleInfo);
345 }
346 }
347 unloadSelftimer_.Unregister(unloadSelftimerId_);
348
349 // match driver failed, waitting to install driver package
350 if (bundleInfo.empty()) {
351 EDM_LOGD(MODULE_DEV_MGR,
352 "deviceId %{public}016" PRIX64 "match driver failed, waitting to install ext driver package", deviceId);
353 return EDM_OK;
354 }
355
356 int32_t ret = AddDevIdOfBundleInfoMap(device, bundleInfo);
357 if (ret != EDM_OK) {
358 EDM_LOGE(MODULE_DEV_MGR, "deviceId[%{public}016" PRIX64 "] update bundle info map failed[%{public}d]", deviceId,
359 ret);
360 return EDM_NOK;
361 }
362 EDM_LOGI(MODULE_DEV_MGR, "successfully match driver[%{public}s], deviceId is %{public}016" PRIx64 "",
363 bundleInfo.c_str(), deviceId);
364
365 return ret;
366 }
367
UnRegisterDevice(const shared_ptr<DeviceInfo> devInfo)368 int32_t ExtDeviceManager::UnRegisterDevice(const shared_ptr<DeviceInfo> devInfo)
369 {
370 BusType type = devInfo->GetBusType();
371 uint64_t deviceId = devInfo->GetDeviceId();
372 shared_ptr<Device> device;
373 string bundleInfo;
374
375 lock_guard<mutex> lock(deviceMapMutex_);
376 if (deviceMap_.find(type) != deviceMap_.end()) {
377 unordered_map<uint64_t, shared_ptr<Device>> &map = deviceMap_[type];
378 if (map.find(deviceId) != map.end()) {
379 device = map[deviceId];
380 bundleInfo = map[deviceId]->GetBundleInfo();
381 map.erase(deviceId);
382 EDM_LOGI(MODULE_DEV_MGR, "successfully unregistered device, deviceId is %{public}016" PRIx64 "", deviceId);
383 UnLoadSelf();
384 }
385 }
386
387 if (bundleInfo.empty()) {
388 EDM_LOGI(MODULE_DEV_MGR, "deviceId %{public}016" PRIX64 " bundleInfo is empty", deviceId);
389 return EDM_OK;
390 }
391
392 int32_t ret = RemoveDevIdOfBundleInfoMap(device, bundleInfo);
393 if (ret != EDM_OK) {
394 EDM_LOGE(
395 MODULE_DEV_MGR, "deviceId[%{public}016" PRIX64 "] remove bundleInfo map failed[%{public}d]", deviceId, ret);
396 return ret;
397 }
398
399 EDM_LOGI(MODULE_DEV_MGR, "successfully remove bundleInfo, deviceId %{public}016" PRIx64 ", bundleInfo[%{public}s]",
400 deviceId, bundleInfo.c_str());
401
402 return EDM_OK;
403 }
404
QueryDevice(const BusType busType)405 vector<shared_ptr<DeviceInfo>> ExtDeviceManager::QueryDevice(const BusType busType)
406 {
407 vector<shared_ptr<DeviceInfo>> devInfoVec;
408
409 lock_guard<mutex> lock(deviceMapMutex_);
410 if (deviceMap_.find(busType) == deviceMap_.end()) {
411 EDM_LOGE(MODULE_DEV_MGR, "no device is found and busType %{public}d is invalid", busType);
412 return devInfoVec;
413 }
414
415 unordered_map<uint64_t, shared_ptr<Device>> map = deviceMap_[busType];
416 for (auto device : map) {
417 devInfoVec.emplace_back(device.second->GetDeviceInfo());
418 }
419 EDM_LOGD(MODULE_DEV_MGR, "find %{public}zu device of busType %{public}d", devInfoVec.size(), busType);
420
421 return devInfoVec;
422 }
423
GetTotalDeviceNum(void) const424 size_t ExtDeviceManager::GetTotalDeviceNum(void) const
425 {
426 // Please do not add lock. This will be called in the UnRegisterDevice.
427 size_t totalNum = 0;
428 for (auto &[_, device] : deviceMap_) {
429 totalNum += device.size();
430 }
431 EDM_LOGD(MODULE_DEV_MGR, "total device num is %{public}zu", totalNum);
432 return totalNum;
433 }
434
UnLoadSelf(void)435 void ExtDeviceManager::UnLoadSelf(void)
436 {
437 unloadSelftimer_.Unregister(unloadSelftimerId_);
438 unloadSelftimer_.Shutdown();
439 if (GetTotalDeviceNum() != 0) {
440 EDM_LOGI(MODULE_DEV_MGR, "not need unload");
441 return;
442 }
443
444 if (auto ret = unloadSelftimer_.Setup(); ret != Utils::TIMER_ERR_OK) {
445 EDM_LOGE(MODULE_DEV_MGR, "set up timer failed %{public}u", ret);
446 return;
447 }
448
449 auto task = []() {
450 auto samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
451 if (samgrProxy == nullptr) {
452 EDM_LOGE(MODULE_DEV_MGR, "get samgr failed");
453 return;
454 }
455
456 auto ret = samgrProxy->UnloadSystemAbility(HDF_EXTERNAL_DEVICE_MANAGER_SA_ID);
457 if (ret != EDM_OK) {
458 EDM_LOGE(MODULE_DEV_MGR, "unload failed");
459 }
460 };
461 unloadSelftimerId_ = unloadSelftimer_.Register(task, UNLOAD_SA_TIMER_INTERVAL, true);
462 }
463
QueryDeviceByDeviceID(uint64_t deviceId)464 std::shared_ptr<Device> ExtDeviceManager::QueryDeviceByDeviceID(uint64_t deviceId)
465 {
466 BusType busType = *reinterpret_cast<BusType *>(&deviceId);
467 EDM_LOGI(MODULE_DEV_MGR, "the busType: %{public}d", static_cast<uint32_t>(busType));
468 auto deviceMapIter = deviceMap_.find(busType);
469 if (deviceMapIter == deviceMap_.end()) {
470 EDM_LOGE(MODULE_DEV_MGR, "can not find device by %{public}d busType", static_cast<uint32_t>(busType));
471 return nullptr;
472 }
473
474 const auto &devices = deviceMapIter->second;
475 auto deviceIter = devices.find(deviceId);
476 if (deviceIter == devices.end()) {
477 EDM_LOGE(MODULE_DEV_MGR, "can not find device by %{public}016" PRIX64 " deviceId", deviceId);
478 return nullptr;
479 }
480
481 EDM_LOGI(MODULE_DEV_MGR, "find device by %{public}016" PRIX64 " deviceId sucessfully", deviceId);
482 return deviceIter->second;
483 }
484
ConnectDevice(uint64_t deviceId,const sptr<IDriverExtMgrCallback> & connectCallback)485 int32_t ExtDeviceManager::ConnectDevice(uint64_t deviceId, const sptr<IDriverExtMgrCallback> &connectCallback)
486 {
487 // find device by deviceId
488 lock_guard<mutex> lock(deviceMapMutex_);
489 std::shared_ptr<Device> device = QueryDeviceByDeviceID(deviceId);
490 if (device == nullptr) {
491 EDM_LOGI(MODULE_DEV_MGR, "failed to find device with %{public}016" PRIX64 " deviceId", deviceId);
492 return EDM_NOK;
493 }
494 return device->Connect(connectCallback);
495 }
496
DisConnectDevice(uint64_t deviceId)497 int32_t ExtDeviceManager::DisConnectDevice(uint64_t deviceId)
498 {
499 lock_guard<mutex> lock(deviceMapMutex_);
500 std::shared_ptr<Device> device = QueryDeviceByDeviceID(deviceId);
501 if (device == nullptr) {
502 EDM_LOGI(MODULE_DEV_MGR, "failed to find device with %{public}016" PRIX64 " deviceId", deviceId);
503 return EDM_NOK;
504 }
505
506 return device->Disconnect();
507 }
508 } // namespace ExternalDeviceManager
509 } // namespace OHOS