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