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