1 /*
2 * Copyright (c) 2021-2024 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 "dp_device_manager.h"
17
18 #include <chrono>
19 #include <thread>
20
21 #include <unistd.h>
22
23 #include "parameter.h"
24
25 #include "device_profile_log.h"
26 #include "device_profile_manager.h"
27 #include "device_profile_utils.h"
28 #include "distributed_device_profile_service.h"
29 #include "dm_constants.h"
30 #include "event_handler_factory.h"
31 #include "ipc_object_proxy.h"
32 #include "ipc_skeleton.h"
33 #include "iservice_registry.h"
34 #include "system_ability_definition.h"
35
36 namespace OHOS {
37 namespace DeviceProfile {
38 using namespace std::chrono_literals;
39 using namespace DistributedHardware;
40
41 namespace {
42 const std::string TAG = "DpDeviceManager";
43
44 constexpr int32_t RETRY_TIMES = 30;
45 constexpr uint8_t MAX_DEVICE_TYPE = 3;
46 constexpr int32_t DEVICE_ID_SIZE = 65;
47 constexpr int32_t MAX_TIMES_CONNECT_DEVICEMANAGER = 10;
48 const std::string PKG_NAME = "ohos.deviceprofile";
49 }
50
51 IMPLEMENT_SINGLE_INSTANCE(DpDeviceManager);
52
GetInitCallback()53 std::shared_ptr<DistributedHardware::DmInitCallback> DpDeviceManager::GetInitCallback()
54 {
55 std::lock_guard<std::mutex> autoLock(initcallbackLock_);
56 if (initCallback_ == nullptr) {
57 initCallback_ = std::make_shared<DeviceInitCallBack>();
58 }
59 return initCallback_;
60 }
61
GetStateCallback()62 std::shared_ptr<DistributedHardware::DeviceStateCallback> DpDeviceManager::GetStateCallback()
63 {
64 std::lock_guard<std::mutex> autoLock(stateCallLock_);
65 if (stateCallback_ == nullptr) {
66 stateCallback_ = std::make_shared<DpDeviceStateCallback>();
67 }
68 return stateCallback_;
69 }
70
GetDevMgrHandler()71 void DpDeviceManager::GetDevMgrHandler()
72 {
73 std::lock_guard<std::mutex> autoLock(devMgrLock_);
74 if (devMgrHandler_ == nullptr) {
75 devMgrHandler_ = DistributedDeviceProfile::EventHandlerFactory::GetInstance().GetEventHandler();
76 }
77 }
78
Init()79 bool DpDeviceManager::Init()
80 {
81 GetInitCallback();
82 GetStateCallback();
83 GetDevMgrHandler();
84 {
85 std::lock_guard<std::mutex> autoLock(devMgrLock_);
86 if (devMgrHandler_ == nullptr) {
87 return false;
88 }
89 }
90 if (!ConnectDeviceManager()) {
91 return false;
92 }
93 return true;
94 }
95
OnRemoteDied()96 void DpDeviceManager::DeviceInitCallBack::OnRemoteDied()
97 {
98 HILOGI("DeviceInitCallBack OnRemoteDied");
99 DpDeviceManager::GetInstance().Init();
100 }
101
GetTrustedDeviceList()102 void DpDeviceManager::GetTrustedDeviceList()
103 {
104 std::vector<DmDeviceInfo> deviceList;
105 int32_t ret = DeviceManager::GetInstance().GetTrustedDeviceList(PKG_NAME, "", deviceList);
106 if (ret != ERR_OK) {
107 HILOGE("GetTrustedDeviceList Failed!");
108 return;
109 }
110 if (deviceList.empty()) {
111 HILOGI("deviceList is empty!");
112 return;
113 }
114 for (const DmDeviceInfo& dmDeviceInfo : deviceList) {
115 auto dpDeviceInfo = std::make_shared<DeviceInfo>(
116 dmDeviceInfo.deviceName, dmDeviceInfo.networkId, dmDeviceInfo.deviceTypeId);
117 DpDeviceManager::GetInstance().OnNodeOnline(dpDeviceInfo);
118 }
119 DistributedDeviceProfileService::GetInstance().DeviceOnline();
120 }
121
OnDeviceOnline(const DmDeviceInfo & deviceInfo)122 void DpDeviceManager::DpDeviceStateCallback::OnDeviceOnline(const DmDeviceInfo &deviceInfo)
123 {
124 HILOGI("online called");
125 auto dpDeviceInfo = std::make_shared<DeviceInfo>(
126 deviceInfo.deviceName, deviceInfo.networkId, deviceInfo.deviceTypeId);
127 DpDeviceManager::GetInstance().OnNodeOnline(dpDeviceInfo);
128 DistributedDeviceProfileService::GetInstance().DeviceOnline();
129 }
130
OnDeviceOffline(const DmDeviceInfo & deviceInfo)131 void DpDeviceManager::DpDeviceStateCallback::OnDeviceOffline(const DmDeviceInfo &deviceInfo)
132 {
133 HILOGI("offline called");
134 std::string networkId = deviceInfo.networkId;
135 DpDeviceManager::GetInstance().OnNodeOffline(networkId);
136 }
137
OnDeviceChanged(const DmDeviceInfo & deviceInfo)138 void DpDeviceManager::DpDeviceStateCallback::OnDeviceChanged(const DmDeviceInfo &deviceInfo)
139 {
140 HILOGD("called");
141 }
142
OnDeviceReady(const DmDeviceInfo & deviceInfo)143 void DpDeviceManager::DpDeviceStateCallback::OnDeviceReady(const DmDeviceInfo &deviceInfo)
144 {
145 HILOGD("called");
146 }
147
OnNodeOnline(const std::shared_ptr<DeviceInfo> deviceInfo)148 void DpDeviceManager::OnNodeOnline(const std::shared_ptr<DeviceInfo> deviceInfo)
149 {
150 if (deviceInfo == nullptr) {
151 HILOGE("deviceInfo is nullptr");
152 return;
153 }
154 auto onlineNotifyTask = [this, deviceInfo = deviceInfo]() {
155 HILOGI("online networkId = %{public}s",
156 DeviceProfileUtils::AnonymizeDeviceId(deviceInfo->GetNetworkId()).c_str());
157 RemoveExpiredDeviceIds(deviceInfo->GetNetworkId());
158 AddDeviceIds(deviceInfo->GetNetworkId());
159 {
160 std::string networkId = deviceInfo->GetNetworkId();
161 std::lock_guard<std::mutex> autoLock(deviceLock_);
162 remoteDeviceInfoMap_[networkId] = deviceInfo;
163 }
164 };
165 std::lock_guard<std::mutex> autoLock(devMgrLock_);
166 if (devMgrHandler_ == nullptr) {
167 HILOGE("devMgrHandler is nullptr");
168 return;
169 }
170 if (!devMgrHandler_->PostTask(onlineNotifyTask)) {
171 HILOGE("post task failed");
172 return;
173 }
174 }
175
OnNodeOffline(const std::string & networkId)176 void DpDeviceManager::OnNodeOffline(const std::string& networkId)
177 {
178 auto offlineNotifyTask = [this, networkId = std::move(networkId)]() {
179 HILOGI("offline networkId = %{public}s", DeviceProfileUtils::AnonymizeDeviceId(networkId).c_str());
180 std::lock_guard<std::mutex> autoLock(deviceLock_);
181 remoteDeviceInfoMap_.erase(networkId);
182 };
183 std::lock_guard<std::mutex> autoLock(devMgrLock_);
184 if (devMgrHandler_ == nullptr) {
185 HILOGE("devMgrHandler is nullptr");
186 return;
187 }
188 if (!devMgrHandler_->PostTask(offlineNotifyTask)) {
189 HILOGE("post task failed");
190 return;
191 }
192 }
193
WaitForDnetworkReady()194 bool DpDeviceManager::WaitForDnetworkReady()
195 {
196 auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
197 if (samgr == nullptr) {
198 HILOGE("WaitForDnetworkReady failed to get samgr!");
199 return false;
200 }
201 int32_t retryTimeout = RETRY_TIMES;
202 do {
203 auto dnetworkDm = samgr->CheckSystemAbility(DISTRIBUTED_HARDWARE_DEVICEMANAGER_SA_ID);
204 auto dnetworkSoftBus = samgr->CheckSystemAbility(SOFTBUS_SERVER_SA_ID);
205 if (dnetworkDm != nullptr && dnetworkSoftBus != nullptr) {
206 IPCObjectProxy* dmProxy = reinterpret_cast<IPCObjectProxy*>(dnetworkDm.GetRefPtr());
207 IPCObjectProxy* sbProxy = reinterpret_cast<IPCObjectProxy*>(dnetworkSoftBus.GetRefPtr());
208 // make sure the proxy is not dead
209 if (dmProxy != nullptr && !dmProxy->IsObjectDead() && sbProxy != nullptr && !sbProxy->IsObjectDead()) {
210 return true;
211 }
212 }
213 HILOGI("Waiting for dnentwork service...");
214 std::this_thread::sleep_for(1s);
215 if (--retryTimeout <= 0) {
216 HILOGI("Waiting for dnentwork service timeout(30)s");
217 return false;
218 }
219 } while (true);
220 return false;
221 }
222
ConnectDeviceManager()223 bool DpDeviceManager::ConnectDeviceManager()
224 {
225 HILOGI("ConnectDeviceManager");
226 bool isReady = WaitForDnetworkReady();
227 if (!isReady) {
228 HILOGE("ConnectDeviceManager wait Dnetwork failed!");
229 return false;
230 }
231
232 auto registerTask = [this]() {
233 HILOGD("register task...");
234 int32_t retryTimes = 0;
235 int32_t errCode = ERR_OK;
236 while (retryTimes++ < MAX_TIMES_CONNECT_DEVICEMANAGER) {
237 int32_t ret = DeviceManager::GetInstance().InitDeviceManager(PKG_NAME, GetInitCallback());
238 if (ret != 0) {
239 HILOGE("init device manager failed, ret:%{public}d", ret);
240 std::this_thread::sleep_for(1s);
241 continue;
242 }
243 errCode = DeviceManager::GetInstance().RegisterDevStateCallback(
244 PKG_NAME, "", GetStateCallback());
245 if (errCode == ERR_OK) {
246 DpDeviceManager::GetInstance().GetTrustedDeviceList();
247 break;
248 }
249 HILOGE("register errCode = %{public}d, retrying...", errCode);
250
251 errCode = DeviceManager::GetInstance().UnRegisterDevStateCallback(PKG_NAME);
252 HILOGI("unregister errCode = %{public}d", errCode);
253 std::this_thread::sleep_for(1s);
254 }
255
256 if (errCode == ERR_OK) {
257 AddLocalDeviceIds();
258 RecoverDevicesIfNeeded();
259 }
260 HILOGI("register %{public}s", (errCode == ERR_OK) ? "success" : "timeout");
261 };
262 std::lock_guard<std::mutex> autoLock(devMgrLock_);
263 if (devMgrHandler_ == nullptr) {
264 HILOGE("devMgrHandler is nullptr");
265 return false;
266 }
267 if (!devMgrHandler_->PostTask(registerTask)) {
268 HILOGE("post task failed");
269 return false;
270 }
271 return true;
272 }
273
RecoverDevicesIfNeeded()274 void DpDeviceManager::RecoverDevicesIfNeeded()
275 {
276 HILOGI("called");
277 std::vector<DmDeviceInfo> deviceList;
278 if (DeviceManager::GetInstance().GetTrustedDeviceList(PKG_NAME, "", deviceList) != ERR_OK) {
279 HILOGE("get all node info failed");
280 return;
281 }
282 for (DmDeviceInfo dmDeviceInfo : deviceList) {
283 std::string networkId = dmDeviceInfo.networkId;
284 HILOGI("deviceId %{public}s found", DeviceProfileUtils::AnonymizeDeviceId(networkId).c_str());
285 AddDeviceIds(networkId);
286 {
287 auto deviceInfo = std::make_shared<DeviceInfo>(
288 dmDeviceInfo.deviceName, dmDeviceInfo.networkId, dmDeviceInfo.deviceTypeId);
289 std::lock_guard<std::mutex> autoLock(deviceLock_);
290 remoteDeviceInfoMap_.emplace(std::move(networkId), deviceInfo);
291 }
292 }
293 }
294
AddLocalDeviceIds()295 void DpDeviceManager::AddLocalDeviceIds()
296 {
297 HILOGI("called");
298 DmDeviceInfo dmInfo;
299 int32_t errCode = DeviceManager::GetInstance().GetLocalDeviceInfo(PKG_NAME, dmInfo);
300 if (errCode != ERR_OK) {
301 HILOGW("errCode = %{public}d", errCode);
302 std::string udid;
303 GetLocalDeviceUdid(udid);
304 std::vector<std::string> deviceIds = {"", std::move(udid), ""};
305 std::lock_guard<std::mutex> autoLock(deviceLock_);
306 deviceIdsList_.emplace_back(std::move(deviceIds));
307 } else {
308 AddDeviceIds(dmInfo.networkId);
309 }
310 }
311
AddDeviceIds(const std::string & networkId)312 void DpDeviceManager::AddDeviceIds(const std::string& networkId)
313 {
314 HILOGI("called");
315 std::string udid;
316 if (GetUdidByNetworkId(networkId, udid)) {
317 HILOGI("udid %{public}s", DeviceProfileUtils::AnonymizeDeviceId(udid).c_str());
318 }
319 std::string uuid;
320 if (GetUuidByNetworkId(networkId, uuid)) {
321 HILOGI("uuid %{public}s", DeviceProfileUtils::AnonymizeDeviceId(uuid).c_str());
322 }
323 std::vector<std::string> deviceIds = {networkId, std::move(udid), std::move(uuid)};
324 std::lock_guard<std::mutex> autoLock(deviceLock_);
325 deviceIdsList_.emplace_back(std::move(deviceIds));
326 }
327
RemoveExpiredDeviceIds(const std::string & networkId)328 void DpDeviceManager::RemoveExpiredDeviceIds(const std::string& networkId)
329 {
330 HILOGI("called");
331 std::string udid;
332 if (!GetUdidByNetworkId(networkId, udid)) {
333 return;
334 }
335 if (udid.empty()) {
336 return;
337 }
338 RemoveDeviceIdsByUdid(udid);
339 }
340
RemoveDeviceIds(const std::string & networkId)341 void DpDeviceManager::RemoveDeviceIds(const std::string& networkId)
342 {
343 HILOGI("called");
344 std::lock_guard<std::mutex> autoLock(deviceLock_);
345 auto iter = std::find_if(deviceIdsList_.begin(), deviceIdsList_.end(), [&networkId](const auto& deviceIds) {
346 return deviceIds[static_cast<uint8_t>(DeviceIdType::NETWORKID)] == networkId;
347 });
348 if (iter != deviceIdsList_.end()) {
349 deviceIdsList_.erase(iter);
350 }
351 return;
352 }
353
RemoveDeviceIdsByUdid(const std::string & udid)354 void DpDeviceManager::RemoveDeviceIdsByUdid(const std::string& udid)
355 {
356 HILOGI("called");
357 std::lock_guard<std::mutex> autoLock(deviceLock_);
358 auto iter = std::find_if(deviceIdsList_.begin(), deviceIdsList_.end(), [&udid](const auto& deviceIds) {
359 return deviceIds[static_cast<uint8_t>(DeviceIdType::UDID)] == udid;
360 });
361 if (iter != deviceIdsList_.end()) {
362 deviceIdsList_.erase(iter);
363 HILOGI("remove device udid %{public}s", DeviceProfileUtils::AnonymizeDeviceId(udid).c_str());
364 }
365 return;
366 }
367
DisconnectDeviceManager()368 bool DpDeviceManager::DisconnectDeviceManager()
369 {
370 int32_t errCode = DeviceManager::GetInstance().UnRegisterDevStateCallback(PKG_NAME);
371 if (errCode != ERR_OK) {
372 HILOGE("remove failed, errCode = %{public}d", errCode);
373 return false;
374 }
375 return true;
376 }
377
GetLocalDeviceUdid(std::string & udid)378 void DpDeviceManager::GetLocalDeviceUdid(std::string& udid)
379 {
380 char localDeviceId[DEVICE_ID_SIZE] = {0};
381 GetDevUdid(localDeviceId, DEVICE_ID_SIZE);
382 udid = localDeviceId;
383 }
384
GetUdidByNetworkId(const std::string & networkId,std::string & udid)385 bool DpDeviceManager::GetUdidByNetworkId(const std::string& networkId, std::string& udid)
386 {
387 return ((DeviceManager::GetInstance().GetUdidByNetworkId(
388 PKG_NAME, networkId, udid) == 0) ? true : false);
389 }
390
GetUuidByNetworkId(const std::string & networkId,std::string & uuid)391 bool DpDeviceManager::GetUuidByNetworkId(const std::string& networkId, std::string& uuid)
392 {
393 return ((DeviceManager::GetInstance().GetUuidByNetworkId(
394 PKG_NAME, networkId, uuid) == 0) ? true : false);
395 }
396
TransformDeviceId(const std::string & fromDeviceId,std::string & toDeviceId,DeviceIdType toType)397 bool DpDeviceManager::TransformDeviceId(const std::string& fromDeviceId,
398 std::string& toDeviceId, DeviceIdType toType)
399 {
400 if (fromDeviceId.empty()) {
401 HILOGW("empty device id");
402 return false;
403 }
404
405 uint8_t idx = static_cast<uint8_t>(toType);
406 if (idx > MAX_DEVICE_TYPE - 1) {
407 return false;
408 }
409
410 toDeviceId = "";
411 std::lock_guard<std::mutex> autoLock(deviceLock_);
412 for (const auto& deviceIds : deviceIdsList_) {
413 auto iter = std::find(deviceIds.begin(), deviceIds.end(), fromDeviceId);
414 if (iter != deviceIds.end()) {
415 toDeviceId = deviceIds[idx];
416 return !toDeviceId.empty();
417 }
418 }
419 return false;
420 }
421
GetDeviceIdList(std::list<std::string> & deviceIdList)422 void DpDeviceManager::GetDeviceIdList(std::list<std::string>& deviceIdList)
423 {
424 deviceIdList.clear();
425 std::lock_guard<std::mutex> autoLock(deviceLock_);
426 for (const auto& [_, deviceInfo] : remoteDeviceInfoMap_) {
427 if (deviceInfo == nullptr) {
428 HILOGW("deviceInfo is nullptr");
429 continue;
430 }
431 deviceIdList.emplace_back(deviceInfo->GetNetworkId());
432 }
433 }
434
GetDeviceList(std::list<std::shared_ptr<DeviceInfo>> & deviceList)435 void DpDeviceManager::GetDeviceList(std::list<std::shared_ptr<DeviceInfo>>& deviceList)
436 {
437 deviceList.clear();
438 std::lock_guard<std::mutex> autoLock(deviceLock_);
439 for (const auto& [_, deviceInfo] : remoteDeviceInfoMap_) {
440 if (deviceInfo == nullptr) {
441 HILOGW("deviceInfo is nullptr");
442 continue;
443 }
444 deviceList.emplace_back(deviceInfo);
445 }
446 }
447 } // namespace DeviceProfile
448 } // namespace OHOS
449