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