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 "distributed_hardware_manager_factory.h"
17 
18 #include <cstdlib>
19 #include <dlfcn.h>
20 #include <pthread.h>
21 #include <string>
22 #include <thread>
23 #include <vector>
24 
25 #include "iservice_registry.h"
26 #include "system_ability_definition.h"
27 
28 #include "dm_device_info.h"
29 #include "device_manager.h"
30 
31 #include "anonymous_string.h"
32 #include "constants.h"
33 #include "dh_context.h"
34 #include "dh_utils_hisysevent.h"
35 #include "dh_utils_hitrace.h"
36 #include "dh_utils_tool.h"
37 #include "distributed_hardware_errno.h"
38 #include "distributed_hardware_log.h"
39 #include "distributed_hardware_manager.h"
40 #include "device_param_mgr.h"
41 #include "meta_info_manager.h"
42 
43 namespace OHOS {
44 namespace DistributedHardware {
45 #undef DH_LOG_TAG
46 #define DH_LOG_TAG "DistributedHardwareManagerFactory"
47 
48 IMPLEMENT_SINGLE_INSTANCE(DistributedHardwareManagerFactory);
InitLocalDevInfo()49 bool DistributedHardwareManagerFactory::InitLocalDevInfo()
50 {
51     DHLOGI("InitLocalDevInfo start");
52     std::vector<DmDeviceInfo> deviceList;
53     DeviceManager::GetInstance().GetTrustedDeviceList(DH_FWK_PKG_NAME, "", deviceList);
54     if (deviceList.size() > 0 && deviceList.size() <= MAX_ONLINE_DEVICE_SIZE) {
55         DHLOGI("There is other device online, on need just init db, use normal logic");
56         return true;
57     }
58     auto initResult = DistributedHardwareManager::GetInstance().LocalInit();
59     if (initResult != DH_FWK_SUCCESS) {
60         DHLOGE("InitLocalDevInfo failed, errCode = %{public}d", initResult);
61         return false;
62     }
63     DHLOGI("InitLocalDevInfo success, check is need exit");
64 
65     deviceList.clear();
66     DeviceManager::GetInstance().GetTrustedDeviceList(DH_FWK_PKG_NAME, "", deviceList);
67     if ((deviceList.size() == 0 || deviceList.size() > MAX_ONLINE_DEVICE_SIZE) &&
68         DHContext::GetInstance().GetIsomerismConnectCount() == 0) {
69         DHLOGI("After InitLocalDevInfo, no device online, exit dhfwk");
70         ExitDHFWK();
71     }
72     return true;
73 }
74 
Init()75 bool DistributedHardwareManagerFactory::Init()
76 {
77     DHLOGI("start");
78     auto initResult = DistributedHardwareManager::GetInstance().Initialize();
79     if (initResult != DH_FWK_SUCCESS) {
80         DHLOGE("Initialize failed, errCode = %{public}d", initResult);
81         return false;
82     }
83     isInit_.store(true);
84     DHLOGI("success");
85     return true;
86 }
87 
UnInit()88 void DistributedHardwareManagerFactory::UnInit()
89 {
90     DHLOGI("start");
91     DHTraceStart(COMPONENT_UNLOAD_START);
92     HiSysEventWriteMsg(DHFWK_EXIT_BEGIN, OHOS::HiviewDFX::HiSysEvent::EventType::BEHAVIOR,
93         "dhfwk sa exit begin.");
94 
95     // release all the resources synchronously
96     DistributedHardwareManager::GetInstance().Release();
97     isInit_.store(false);
98     flagUnInit_.store(false);
99     DHTraceEnd();
100     CheckExitSAOrNot();
101 }
102 
ExitDHFWK()103 void DistributedHardwareManagerFactory::ExitDHFWK()
104 {
105     DHLOGI("No device online or deviceList is over size, exit sa process");
106     HiSysEventWriteMsg(DHFWK_EXIT_END, OHOS::HiviewDFX::HiSysEvent::EventType::BEHAVIOR,
107         "dhfwk sa exit end.");
108     auto systemAbilityMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
109     if (systemAbilityMgr == nullptr) {
110         DHLOGE("systemAbilityMgr is null");
111         return;
112     }
113     int32_t ret = systemAbilityMgr->UnloadSystemAbility(DISTRIBUTED_HARDWARE_SA_ID);
114     if (ret != DH_FWK_SUCCESS) {
115         DHLOGE("systemAbilityMgr UnLoadSystemAbility failed, ret: %{public}d", ret);
116         return;
117     }
118     DHLOGI("systemAbilityMgr UnLoadSystemAbility success");
119 }
120 
CheckExitSAOrNot()121 void DistributedHardwareManagerFactory::CheckExitSAOrNot()
122 {
123     std::vector<DmDeviceInfo> deviceList;
124     DeviceManager::GetInstance().GetTrustedDeviceList(DH_FWK_PKG_NAME, "", deviceList);
125     if ((deviceList.size() == 0 || deviceList.size() > MAX_ONLINE_DEVICE_SIZE) &&
126         DHContext::GetInstance().GetIsomerismConnectCount() == 0) {
127         ExitDHFWK();
128         return;
129     }
130 
131     DHLOGI("After uninit, DM report devices online, reinit");
132     Init();
133     for (const auto &deviceInfo : deviceList) {
134         const auto networkId = std::string(deviceInfo.networkId);
135         const auto uuid = GetUUIDByDm(networkId);
136         const auto udid = GetUDIDByDm(networkId);
137         DHLOGI("Send trusted device online, networkId = %{public}s, uuid = %{public}s",
138             GetAnonyString(networkId).c_str(),
139             GetAnonyString(uuid).c_str());
140         uint16_t deviceType = deviceInfo.deviceTypeId;
141         std::thread([this, networkId, uuid, udid, deviceType]() {
142             this->SendOnLineEvent(networkId, uuid, udid, deviceType);
143         }).detach();
144     }
145 }
146 
IsInit()147 bool DistributedHardwareManagerFactory::IsInit()
148 {
149     return isInit_.load();
150 }
151 
SendOnLineEvent(const std::string & networkId,const std::string & uuid,const std::string & udid,uint16_t deviceType)152 int32_t DistributedHardwareManagerFactory::SendOnLineEvent(const std::string &networkId, const std::string &uuid,
153     const std::string &udid, uint16_t deviceType)
154 {
155     if (!IsIdLengthValid(networkId) || !IsIdLengthValid(uuid) || !IsIdLengthValid(udid)) {
156         return ERR_DH_FWK_PARA_INVALID;
157     }
158     int32_t ret = pthread_setname_np(pthread_self(), SEND_ONLINE);
159     if (ret != DH_FWK_SUCCESS) {
160         DHLOGE("SendOnLineEvent setname failed.");
161     }
162 
163     if (flagUnInit_.load()) {
164         DHLOGE("is in uniniting, can not process online event.");
165         return ERR_DH_FWK_HARDWARE_MANAGER_INIT_FAILED;
166     }
167 
168     if (DHContext::GetInstance().IsDeviceOnline(uuid)) {
169         DHLOGW("device is already online, uuid = %{public}s", GetAnonyString(uuid).c_str());
170         return ERR_DH_FWK_HARDWARE_MANAGER_DEVICE_REPEAT_ONLINE;
171     }
172 
173     DHContext::GetInstance().AddOnlineDevice(udid, uuid, networkId);
174     DHContext::GetInstance().AddRealTimeOnlineDeviceNetworkId(networkId);
175 
176     if (!isInit_.load() && !Init()) {
177         DHLOGE("distributedHardwareMgr is null");
178         return ERR_DH_FWK_HARDWARE_MANAGER_INIT_FAILED;
179     }
180 
181     if (DeviceParamMgr::GetInstance().IsDeviceE2ESync()) {
182         DHLOGI("e2e device, need initiative sync data.");
183         MetaInfoManager::GetInstance()->SyncDataByNetworkId(networkId);
184     }
185     auto onlineResult = DistributedHardwareManager::GetInstance().SendOnLineEvent(networkId, uuid, udid, deviceType);
186     if (onlineResult != DH_FWK_SUCCESS) {
187         DHLOGE("online failed, errCode = %{public}d", onlineResult);
188         return onlineResult;
189     }
190     return DH_FWK_SUCCESS;
191 }
192 
SendOffLineEvent(const std::string & networkId,const std::string & uuid,const std::string & udid,uint16_t deviceType)193 int32_t DistributedHardwareManagerFactory::SendOffLineEvent(const std::string &networkId, const std::string &uuid,
194     const std::string &udid, uint16_t deviceType)
195 {
196     if (!IsIdLengthValid(networkId) || !IsIdLengthValid(uuid) || !IsIdLengthValid(udid)) {
197         return ERR_DH_FWK_PARA_INVALID;
198     }
199     if (!isInit_.load() && !Init()) {
200         DHLOGE("distributedHardwareMgr is null");
201         return ERR_DH_FWK_HARDWARE_MANAGER_INIT_FAILED;
202     }
203 
204     if (!DHContext::GetInstance().IsDeviceOnline(uuid)) {
205         DHLOGE("Device not online, networkId: %{public}s, uuid: %{public}s",
206             GetAnonyString(networkId).c_str(), GetAnonyString(uuid).c_str());
207         return ERR_DH_FWK_HARDWARE_MANAGER_DEVICE_REPEAT_OFFLINE;
208     }
209 
210     DHContext::GetInstance().DeleteRealTimeOnlineDeviceNetworkId(networkId);
211     if (DHContext::GetInstance().GetRealTimeOnlineDeviceCount() == 0 &&
212         DHContext::GetInstance().GetIsomerismConnectCount() == 0) {
213         flagUnInit_.store(true);
214         DHLOGI("no online device, set uninit flag true");
215     }
216 
217     auto offlineResult = DistributedHardwareManager::GetInstance().SendOffLineEvent(networkId, uuid, udid, deviceType);
218     if (offlineResult != DH_FWK_SUCCESS) {
219         DHLOGE("offline failed, errCode = %{public}d", offlineResult);
220     }
221     return DH_FWK_SUCCESS;
222 }
223 
GetComponentVersion(std::unordered_map<DHType,std::string> & versionMap)224 int32_t DistributedHardwareManagerFactory::GetComponentVersion(std::unordered_map<DHType, std::string> &versionMap)
225 {
226     DHLOGI("start");
227     return DistributedHardwareManager::GetInstance().GetComponentVersion(versionMap);
228 }
229 
Dump(const std::vector<std::string> & argsStr,std::string & result)230 int32_t DistributedHardwareManagerFactory::Dump(const std::vector<std::string> &argsStr, std::string &result)
231 {
232     return DistributedHardwareManager::GetInstance().Dump(argsStr, result);
233 }
234 
GetUnInitFlag()235 bool DistributedHardwareManagerFactory::GetUnInitFlag()
236 {
237     return flagUnInit_.load();
238 }
239 } // namespace DistributedHardware
240 } // namespace OHOS
241