1 /*
2 * Copyright (c) 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 "all_connect/all_connect_manager.h"
17
18 #include <cstdio>
19 #include <cstdlib>
20 #include <dlfcn.h>
21 #include <thread>
22
23 #include "dfs_error.h"
24 #include "network/softbus/softbus_asset_recv_listener.h"
25 #include "network/softbus/softbus_asset_send_listener.h"
26 #include "network/softbus/softbus_handler.h"
27 #include "utils_directory.h"
28 #include "utils_log.h"
29
30 namespace OHOS {
31 namespace Storage {
32 namespace DistributedFile {
33 #ifdef __LP64__
34 constexpr const char *ALL_CONNECT_SO_PATH = "/system/lib64/";
35 #else
36 constexpr const char *ALL_CONNECT_SO_PATH = "/system/lib/";
37 #endif
38 constexpr const char *ALL_CONNECT_SO_NAME = "libcfwk_allconnect_client.z.so";
39 std::shared_ptr<BlockObject<bool>> AllConnectManager::applyResultBlock_;
40 constexpr int32_t DFS_QOS_TYPE_MIN_BW = 90 * 1024 * 1024;
41 constexpr int32_t DFS_QOS_TYPE_MAX_LATENCY = 10000;
42 constexpr int32_t DFS_QOS_TYPE_MIN_LATENCY = 2000;
AllConnectManager()43 AllConnectManager::AllConnectManager()
44 {
45 allConnectCallback_.OnStop = &AllConnectManager::OnStop;
46 allConnectCallback_.ApplyResult = &AllConnectManager::ApplyResult;
47 }
48
GetInstance()49 AllConnectManager &AllConnectManager::GetInstance()
50 {
51 static AllConnectManager instance;
52 return instance;
53 }
54
InitAllConnectManager()55 int32_t AllConnectManager::InitAllConnectManager()
56 {
57 LOGI("InitAllConnectManager begin");
58 int32_t ret = GetAllConnectSoLoad();
59 if (ret != FileManagement::ERR_OK) {
60 LOGE("InitAllConnectManager failed, all connect so not exist or load so error, ret %{public}d", ret);
61 return ret;
62 }
63
64 ret = RegisterLifecycleCallback();
65 if (ret != FileManagement::ERR_OK) {
66 LOGE("InitAllConnectManager failed, register lifecycle callback error, ret %{public}d", ret);
67 return ret;
68 }
69 LOGI("InitAllConnectManager success");
70 return FileManagement::ERR_OK;
71 }
72
UnInitAllConnectManager()73 int32_t AllConnectManager::UnInitAllConnectManager()
74 {
75 LOGI("UnInitAllConnectManager begin");
76 int32_t ret = UnRegisterLifecycleCallback();
77 if (ret != FileManagement::ERR_OK) {
78 LOGE("UnInitAllConnectManagerfailed, unregister lifecycle callback error, ret %{public}d", ret);
79 }
80
81 std::lock_guard<std::mutex> lock(allConnectLock_);
82 dlclose(dllHandle_);
83 dllHandle_ = nullptr;
84 return FileManagement::ERR_OK;
85 }
86
PublishServiceState(DfsConnectCode code,const std::string & peerNetworkId,ServiceCollaborationManagerBussinessStatus state)87 int32_t AllConnectManager::PublishServiceState(DfsConnectCode code, const std::string &peerNetworkId,
88 ServiceCollaborationManagerBussinessStatus state)
89 {
90 LOGI("PublishServiceState NetworkId: %{public}s, %{public}d begin",
91 Utils::GetAnonyString(peerNetworkId).c_str(), state);
92 std::lock_guard<std::mutex> lock(allConnectLock_);
93 if (dllHandle_ == nullptr) {
94 LOGE("dllHandle_ is nullptr, all connect not support.");
95 return FileManagement::ERR_OK;
96 }
97 if (allConnect_.ServiceCollaborationManager_PublishServiceState == nullptr) {
98 LOGE("PublishServiceState is nullptr, all connect function not load.");
99 return FileManagement::ERR_DLOPEN;
100 }
101
102 if (!GetPublicState(code, peerNetworkId, state)) {
103 return FileManagement::ERR_OK;
104 }
105 int32_t ret = allConnect_.ServiceCollaborationManager_PublishServiceState(peerNetworkId.c_str(),
106 SERVICE_NAME.c_str(),
107 "", state);
108 if (ret != FileManagement::ERR_OK) {
109 LOGE("PublishServiceState %{public}d fail, ret %{public}d", state, ret);
110 return FileManagement::ERR_PUBLISH_STATE;
111 }
112 return FileManagement::ERR_OK;
113 }
114
GetPublicState(DfsConnectCode code,const std::string & peerNetworkId,ServiceCollaborationManagerBussinessStatus state)115 bool AllConnectManager::GetPublicState(DfsConnectCode code, const std::string &peerNetworkId,
116 ServiceCollaborationManagerBussinessStatus state)
117 {
118 std::lock_guard<std::mutex> lock(connectStatesMutex_);
119 auto connectStateIter = connectStates_.find(peerNetworkId);
120 if (connectStateIter == connectStates_.end()) {
121 std::map<DfsConnectCode, ServiceCollaborationManagerBussinessStatus> tmp;
122 tmp.insert(std::make_pair(code, state));
123 connectStates_.insert(std::make_pair(peerNetworkId, tmp));
124 return state == SCM_CONNECTED;
125 }
126 auto &connectState = connectStateIter->second;
127
128 auto it = connectState.find(code);
129 if (it == connectState.end()) {
130 connectState.insert(std::make_pair(code, state));
131 return state == SCM_CONNECTED;
132 }
133 if (state == it->second) {
134 return false;
135 }
136
137 // connect -> idle
138 if (state == SCM_IDLE && it->second == SCM_CONNECTED) {
139 connectState[code] = state;
140 for (auto iter : connectState) {
141 if (iter.second == SCM_CONNECTED) {
142 return false;
143 }
144 }
145 return true;
146 }
147 // idle -> connect
148 connectState[code] = state;
149 return true;
150 }
151
ApplyAdvancedResource(const std::string & peerNetworkId,ServiceCollaborationManager_ResourceRequestInfoSets * resourceRequest)152 int32_t AllConnectManager::ApplyAdvancedResource(const std::string &peerNetworkId,
153 ServiceCollaborationManager_ResourceRequestInfoSets *resourceRequest)
154 {
155 LOGI("ApplyAdvancedResource begin, peerNetworkId: %{public}s", Utils::GetAnonyString(peerNetworkId).c_str());
156 std::lock_guard<std::mutex> lock(allConnectLock_);
157 if (dllHandle_ == nullptr) {
158 LOGE("dllHandle_ is nullptr, all connect not support.");
159 return FileManagement::ERR_OK;
160 }
161 if (allConnect_.ServiceCollaborationManager_ApplyAdvancedResource == nullptr) {
162 LOGE("PublishServiceState is nullptr, all connect function not load.");
163 return FileManagement::ERR_DLOPEN;
164 }
165
166 if (applyResultBlock_ == nullptr) {
167 applyResultBlock_ = std::make_shared<BlockObject<bool>>(BLOCK_INTERVAL_ALLCONNECT, false);
168 }
169
170 int32_t ret = allConnect_.ServiceCollaborationManager_ApplyAdvancedResource(peerNetworkId.c_str(),
171 SERVICE_NAME.c_str(),
172 resourceRequest,
173 &allConnectCallback_);
174 if (ret != FileManagement::ERR_OK) {
175 LOGE("ApplyAdvancedResource fail, ret %{public}d", ret);
176 return FileManagement::ERR_APPLY_RESULT;
177 }
178 auto success = applyResultBlock_->GetValue();
179 if (!success) {
180 LOGE("applyResult is reject, peerNetworkId: %{public}s", Utils::GetAnonyString(peerNetworkId).c_str());
181 return FileManagement::ERR_APPLY_RESULT;
182 }
183 LOGI("ApplyAdvancedResource success, peerNetworkId: %{public}s", Utils::GetAnonyString(peerNetworkId).c_str());
184 return FileManagement::ERR_OK;
185 }
186
GetAllConnectSoLoad()187 int32_t AllConnectManager::GetAllConnectSoLoad()
188 {
189 LOGI("GetAllConnectSoLoad begin");
190 std::lock_guard<std::mutex> lock(allConnectLock_);
191 char path[PATH_MAX + 1] = {0x00};
192 std::string soPathName = std::string(ALL_CONNECT_SO_PATH) + std::string(ALL_CONNECT_SO_NAME);
193 if (soPathName.empty() || (soPathName.length() > PATH_MAX) ||
194 (realpath(soPathName.c_str(), path) == nullptr)) {
195 LOGE("all connect so load failed, soPath=%{public}s not exist.", soPathName.c_str());
196 return FileManagement::ERR_DLOPEN;
197 }
198
199 int32_t (*allConnectProxy)(ServiceCollaborationManager_API *exportapi) = nullptr;
200
201 dllHandle_ = dlopen(path, RTLD_LAZY);
202 if (dllHandle_ == nullptr) {
203 LOGE("dlopen fail");
204 return FileManagement::ERR_DLOPEN;
205 }
206
207 allConnectProxy = reinterpret_cast<int32_t (*)(ServiceCollaborationManager_API *exportapi)>(
208 dlsym(dllHandle_, "ServiceCollaborationManager_Export"));
209 if (allConnectProxy == nullptr) {
210 dlclose(dllHandle_);
211 dllHandle_ = nullptr;
212 LOGE("dlsym allConnectProxy fail");
213 return FileManagement::ERR_DLOPEN;
214 }
215
216 int32_t ret = allConnectProxy(&allConnect_);
217 if (ret != FileManagement::ERR_OK) {
218 dlclose(dllHandle_);
219 dllHandle_ = nullptr;
220 LOGE("get function struct fail, ret %{public}d", ret);
221 return FileManagement::ERR_DLOPEN;
222 }
223 LOGI("so load success");
224 return FileManagement::ERR_OK;
225 }
226
RegisterLifecycleCallback()227 int32_t AllConnectManager::RegisterLifecycleCallback()
228 {
229 LOGI("RegisterLifecycleCallback begin");
230 std::lock_guard<std::mutex> lock(allConnectLock_);
231 if (dllHandle_ == nullptr) {
232 LOGE("dllHandle_ is nullptr, all connect so has not been loaded.");
233 return FileManagement::ERR_DLOPEN;
234 }
235 if (allConnect_.ServiceCollaborationManager_RegisterLifecycleCallback == nullptr) {
236 LOGE("RegisterLifecycleCallback is nullptr, all connect function not load.");
237 return FileManagement::ERR_DLOPEN;
238 }
239
240 int32_t ret = allConnect_.ServiceCollaborationManager_RegisterLifecycleCallback(SERVICE_NAME.c_str(),
241 &allConnectCallback_);
242 if (ret != FileManagement::ERR_OK) {
243 LOGE("RegisterLifecycleCallback fail, ret %{public}d", ret);
244 return FileManagement::ERR_ALLCONNECT;
245 }
246 return FileManagement::ERR_OK;
247 }
248
UnRegisterLifecycleCallback()249 int32_t AllConnectManager::UnRegisterLifecycleCallback()
250 {
251 LOGI("UnRegisterLifecycleCallback begin");
252 std::lock_guard<std::mutex> lock(allConnectLock_);
253 if (dllHandle_ == nullptr) {
254 LOGE("dllHandle_ is nullptr, all connect so has not been loaded.");
255 return FileManagement::ERR_DLOPEN;
256 }
257 if (allConnect_.ServiceCollaborationManager_UnRegisterLifecycleCallback == nullptr) {
258 LOGE("RegisterLifecycleCallback is nullptr, all connect function not load.");
259 return FileManagement::ERR_DLOPEN;
260 }
261
262 int32_t ret = allConnect_.ServiceCollaborationManager_UnRegisterLifecycleCallback(SERVICE_NAME.c_str());
263 if (ret != FileManagement::ERR_OK) {
264 LOGE("UnRegisterLifecycleCallback fail, ret %{public}d", ret);
265 return FileManagement::ERR_ALLCONNECT;
266 }
267 return FileManagement::ERR_OK;
268 }
269
ApplyResult(int32_t errorcode,int32_t result,const char * reason)270 int32_t AllConnectManager::ApplyResult(int32_t errorcode, int32_t result, const char *reason)
271 {
272 (void)reason;
273 LOGI("ApplyResult begin");
274 if (result != PASS) {
275 LOGE("Apply Result is Reject, errorcode is %{public}d", errorcode);
276 applyResultBlock_->SetValue(false);
277 return FileManagement::ERR_APPLY_RESULT;
278 }
279 applyResultBlock_->SetValue(true);
280 return FileManagement::ERR_OK;
281 }
282
OnStop(const char * peerNetworkId)283 int32_t AllConnectManager::OnStop(const char *peerNetworkId)
284 {
285 std::string pNetworkId(peerNetworkId);
286 LOGI("OnStop begin, peerNetworkId:%{public}s", Utils::GetAnonyString(pNetworkId).c_str());
287 std::thread([pNetworkId]() {
288 SoftBusHandler::GetInstance().CopyOnStop(pNetworkId);
289 SoftbusAssetRecvListener::DisConnectByAllConnect(pNetworkId);
290 SoftBusAssetSendListener::DisConnectByAllConnect(pNetworkId);
291 }).detach();
292 return FileManagement::ERR_OK;
293 }
294
BuildResourceRequest()295 std::shared_ptr<ServiceCollaborationManager_ResourceRequestInfoSets> AllConnectManager::BuildResourceRequest()
296 {
297 auto resourceRequest = std::make_shared<ServiceCollaborationManager_ResourceRequestInfoSets>();
298
299 if (remoteHardwareList_ == nullptr) {
300 remoteHardwareList_ = std::make_shared<ServiceCollaborationManager_HardwareRequestInfo>();
301 remoteHardwareList_->hardWareType = ServiceCollaborationManagerHardwareType::SCM_DISPLAY;
302 remoteHardwareList_->canShare = true;
303 }
304 resourceRequest->remoteHardwareListSize = 1;
305 resourceRequest->remoteHardwareList = remoteHardwareList_.get();
306
307 if (localHardwareList_ == nullptr) {
308 localHardwareList_ = std::make_shared<ServiceCollaborationManager_HardwareRequestInfo>();
309 localHardwareList_->hardWareType = ServiceCollaborationManagerHardwareType::SCM_DISPLAY;
310 localHardwareList_->canShare = true;
311 }
312 resourceRequest->localHardwareListSize = 1;
313 resourceRequest->localHardwareList = localHardwareList_.get();
314
315 if (communicationRequest_ == nullptr) {
316 communicationRequest_ = std::make_shared<ServiceCollaborationManager_CommunicationRequestInfo>();
317 communicationRequest_->minBandwidth = DFS_QOS_TYPE_MIN_BW;
318 communicationRequest_->maxLatency = DFS_QOS_TYPE_MAX_LATENCY;
319 communicationRequest_->minLatency = DFS_QOS_TYPE_MIN_LATENCY;
320 communicationRequest_->maxWaitTime = 0;
321 communicationRequest_->dataType = "DATA_TYPE_FILE";
322 }
323 resourceRequest->communicationRequest = communicationRequest_.get();
324
325 return resourceRequest;
326 }
327 } // namespace DistributedFile
328 } // namespace Storage
329 } // namespace OHOS