• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "dsched_all_connect_manager.h"
17 
18 #include <dlfcn.h>
19 
20 #include "distributed_sched_utils.h"
21 #include "dsched_transport_softbus_adapter.h"
22 #include "dtbschedmgr_log.h"
23 
24 namespace OHOS {
25 namespace DistributedSchedule {
26 namespace {
27 const std::string TAG = "DSchedAllConnectManager";
28 constexpr int32_t CONNECT_DECISION_WAIT_S = 60;
29 }
30 
31 IMPLEMENT_SINGLE_INSTANCE(DSchedAllConnectManager);
32 
33 ServiceCollaborationManager_HardwareRequestInfo DSchedAllConnectManager::locReqInfo_ = {
34     .hardWareType = ServiceCollaborationManagerHardwareType::SCM_DISPLAY,
35     .canShare = true,
36 };
37 ServiceCollaborationManager_HardwareRequestInfo DSchedAllConnectManager::rmtReqInfo_ = {
38     .hardWareType = ServiceCollaborationManagerHardwareType::SCM_DISPLAY,
39     .canShare = true,
40 };
41 ServiceCollaborationManager_CommunicationRequestInfo DSchedAllConnectManager::communicationRequest_ = {
42     .minBandwidth = DSCHED_QOS_TYPE_MIN_BW,
43     .maxLatency = DSCHED_QOS_TYPE_MAX_LATENCY,
44     .minLatency = DSCHED_QOS_TYPE_MIN_LATENCY,
45     .maxWaitTime = 0,
46     .dataType = "DATA_TYPE_BYTES",
47 };
48 std::queue<std::string> DSchedAllConnectManager::peerConnectCbQueue_;
49 
InitAllConnectManager()50 int32_t DSchedAllConnectManager::InitAllConnectManager()
51 {
52     HILOGI("Init bind manager.");
53     int32_t ret = GetServiceCollaborationManagerProxy();
54     if (ret != ERR_OK) {
55         HILOGE("GetServiceCollaborationManagerProxy fail, ret %{public}d.", ret);
56         return ret;
57     }
58 
59     ret = RegistLifecycleCallback();
60     if (ret != ERR_OK) {
61         HILOGE("Regist lifecycle callback fail, ret %{public}d.", ret);
62         return ret;
63     }
64     return ERR_OK;
65 }
66 
UninitAllConnectManager()67 int32_t DSchedAllConnectManager::UninitAllConnectManager()
68 {
69     HILOGI("Uninit bind manager enter.");
70     int32_t ret = UnregistLifecycleCallback();
71     if (ret != ERR_OK) {
72         HILOGE("Unregist lifecycle callback fail, ret %{public}d.", ret);
73     }
74 #ifndef TEST_COVERAGE
75     dlclose(dllHandle_);
76 #endif
77     dllHandle_ = nullptr;
78     allConnectMgrApi_ = {
79         .ServiceCollaborationManager_PublishServiceState = nullptr,
80         .ServiceCollaborationManager_ApplyAdvancedResource = nullptr,
81         .ServiceCollaborationManager_RegisterLifecycleCallback = nullptr,
82         .ServiceCollaborationManager_UnRegisterLifecycleCallback = nullptr,
83     };
84     return ERR_OK;
85 }
86 
GetServiceCollaborationManagerProxy()87 int32_t DSchedAllConnectManager::GetServiceCollaborationManagerProxy()
88 {
89     HILOGI("Get service collaboration manager proxy for all connect.");
90     std::lock_guard<std::mutex> autoLock(allConnectMgrLock_);
91 #if (defined(__aarch64__) || defined(__x86_64__))
92     std::string resolvedPath = "/system/lib64/libcfwk_allconnect_client.z.so";
93 #else
94     std::string resolvedPath = "/system/lib/libcfwk_allconnect_client.z.so";
95 #endif
96     char path[PATH_MAX + 1] = {0};
97     if (resolvedPath.length() > PATH_MAX || realpath(resolvedPath.c_str(), path) == nullptr) {
98         HILOGE("Check all connect so real path failed, resolvedPath [%{public}s].",
99             GetAnonymStr(resolvedPath).c_str());
100         return INVALID_PARAMETERS_ERR;
101     }
102     int32_t (*ServiceCollaborationManagerExport)(ServiceCollaborationManager_API *exportapi) = nullptr;
103 
104     dllHandle_ = dlopen(resolvedPath.c_str(), RTLD_LAZY);
105     if (dllHandle_ == nullptr) {
106         HILOGE("Open dms interactive adapter shared object fail, resolvedPath [%{public}s].",
107             GetAnonymStr(resolvedPath).c_str());
108         return NOT_FIND_SERVICE_REGISTRY;
109     }
110 
111     int32_t ret = ERR_OK;
112     do {
113         ServiceCollaborationManagerExport =
114             reinterpret_cast<int32_t (*)(ServiceCollaborationManager_API *exportapi)>(
115             dlsym(dllHandle_, "ServiceCollaborationManager_Export"));
116         if (ServiceCollaborationManagerExport == nullptr) {
117             HILOGE("Link the ServiceCollaborationManagerExport symbol in dms interactive adapter fail.");
118             ret = NOT_FIND_SERVICE_REGISTRY;
119             break;
120         }
121 
122         ret = ServiceCollaborationManagerExport(&allConnectMgrApi_);
123         if (ret != ERR_OK) {
124             HILOGE("Init remote dms interactive adapter proxy fail, ret %{public}d.", ret);
125             break;
126         }
127         HILOGI("Init remote dms interactive adapter proxy success.");
128     } while (false);
129 
130     if (ret != ERR_OK) {
131         HILOGE("Get remote dms interactive adapter proxy fail, dlclose handle.");
132 #ifndef TEST_COVERAGE
133         dlclose(dllHandle_);
134 #endif
135         dllHandle_ = nullptr;
136     }
137     return ret;
138 }
139 
RegistLifecycleCallback()140 int32_t DSchedAllConnectManager::RegistLifecycleCallback()
141 {
142     std::lock_guard<std::mutex> autoLock(allConnectMgrLock_);
143     HILOGI("Regist lifecycle callback.");
144     if (allConnectMgrApi_.ServiceCollaborationManager_RegisterLifecycleCallback == nullptr) {
145         HILOGE("Dms all connect manager RegisterLifecycleCallback api is null.");
146         return INVALID_PARAMETERS_ERR;
147     }
148 
149     ServiceCollaborationManager_Callback bindMgrRegLfCB = {
150         .OnStop = &DSchedAllConnectManager::OnStop,
151         .ApplyResult = &DSchedAllConnectManager::ApplyResult,
152     };
153 
154     int32_t ret = allConnectMgrApi_.ServiceCollaborationManager_RegisterLifecycleCallback(
155         DMS_BIND_MGR_SRV_NAME, &bindMgrRegLfCB);
156     if (ret != ERR_OK) {
157         HILOGE("Dms all connect manager regist lifecycle callback fail, ret %{public}d.", ret);
158     }
159     return ret;
160 }
161 
UnregistLifecycleCallback()162 int32_t DSchedAllConnectManager::UnregistLifecycleCallback()
163 {
164     std::lock_guard<std::mutex> autoLock(allConnectMgrLock_);
165     HILOGI("Unregist lifecycle callback.");
166     if (allConnectMgrApi_.ServiceCollaborationManager_UnRegisterLifecycleCallback == nullptr) {
167         HILOGE("Dms all connect manager UnRegisterLifecycleCallback api is null.");
168         return INVALID_PARAMETERS_ERR;
169     }
170 
171     int32_t ret = allConnectMgrApi_.ServiceCollaborationManager_UnRegisterLifecycleCallback(
172         DMS_BIND_MGR_SRV_NAME);
173     if (ret != ERR_OK) {
174         HILOGE("Dms all connect manager unregist lifecycle callback fail, ret %{public}d.", ret);
175     }
176     return ret;
177 }
178 
PublishServiceState(const std::string & peerNetworkId,const std::string & extraInfo,ServiceCollaborationManagerBussinessStatus state)179 int32_t DSchedAllConnectManager::PublishServiceState(const std::string &peerNetworkId, const std::string &extraInfo,
180     ServiceCollaborationManagerBussinessStatus state)
181 {
182     std::lock_guard<std::mutex> autoLock(allConnectMgrLock_);
183     HILOGI("Publish service state enter, peerNetworkId %{public}s, extraInfo %{public}s, state %{public}d.",
184         GetAnonymStr(peerNetworkId).c_str(), extraInfo.c_str(), state);
185     if (allConnectMgrApi_.ServiceCollaborationManager_PublishServiceState == nullptr) {
186         HILOGE("Dms all connect manager PublishServiceState api is null.");
187         return INVALID_PARAMETERS_ERR;
188     }
189 
190     int32_t ret = allConnectMgrApi_.ServiceCollaborationManager_PublishServiceState(peerNetworkId.c_str(),
191         DMS_BIND_MGR_SRV_NAME, extraInfo.c_str(), state);
192     if (ret != ERR_OK) {
193         HILOGE("Dms all connect manager publish service state fail, ret %{public}d.", ret);
194     }
195     return ret;
196 }
197 
ApplyAdvanceResource(const std::string & peerNetworkId,ServiceCollaborationManager_ResourceRequestInfoSets reqInfoSets)198 int32_t DSchedAllConnectManager::ApplyAdvanceResource(const std::string &peerNetworkId,
199     ServiceCollaborationManager_ResourceRequestInfoSets reqInfoSets)
200 {
201     int32_t ret = ERR_OK;
202     {
203         std::lock_guard<std::mutex> autoLock(allConnectMgrLock_);
204         HILOGI("Apply advance resource enter, peerNetworkId %{public}s.", GetAnonymStr(peerNetworkId).c_str());
205         if (allConnectMgrApi_.ServiceCollaborationManager_ApplyAdvancedResource == nullptr) {
206             HILOGE("Dms all connect manager ApplyAdvancedResource api is null.");
207             return ERR_OK;
208         }
209 
210         peerConnectCbQueue_.push(peerNetworkId);
211         ServiceCollaborationManager_Callback applyScmCbApi = {
212             .OnStop = &DSchedAllConnectManager::OnStop,
213             .ApplyResult = &DSchedAllConnectManager::ApplyResult,
214         };
215         ret = allConnectMgrApi_.ServiceCollaborationManager_ApplyAdvancedResource(peerNetworkId.c_str(),
216             DMS_BIND_MGR_SRV_NAME, &reqInfoSets, &applyScmCbApi);
217         if (ret != ERR_OK) {
218             HILOGE("Dms all connect manager apply advanced resource fail, ret %{public}d.", ret);
219             return ret;
220         }
221     }
222 
223     ret = WaitAllConnectApplyCb(peerNetworkId);
224     if (ret != ERR_OK) {
225         HILOGE("Wait all connect manager apply callback fail, ret %{public}d.", ret);
226     }
227     return ret;
228 }
229 
WaitAllConnectApplyCb(const std::string & peerNetworkId)230 int32_t DSchedAllConnectManager::WaitAllConnectApplyCb(const std::string &peerNetworkId)
231 {
232     std::unique_lock<std::mutex> decisionLock(connectDecisionMutex_);
233     connectDecisionCond_.wait_for(decisionLock, std::chrono::seconds(CONNECT_DECISION_WAIT_S),
234         [this, peerNetworkId]() {
235             return peerConnectDecision_.find(peerNetworkId) != peerConnectDecision_.end();
236         });
237 
238     if (peerConnectDecision_.find(peerNetworkId) == peerConnectDecision_.end()) {
239         HILOGE("Not find peerNetworkId %{public}s in peerConnectDecision.", GetAnonymStr(peerNetworkId).c_str());
240         return DMS_CONNECT_APPLY_TIMEOUT_FAILED;
241     }
242     int32_t ret = peerConnectDecision_.at(peerNetworkId).load() ? ERR_OK : DMS_CONNECT_APPLY_REJECT_FAILED;
243     HILOGI("Wait all connect apply decision callback end, peerNetworkId %{public}s, isSupport %{public}d.",
244         GetAnonymStr(peerNetworkId).c_str(), peerConnectDecision_.at(peerNetworkId).load());
245     peerConnectDecision_.erase(peerNetworkId);
246     return ret;
247 }
248 
NotifyAllConnectDecision(const std::string & peerNetworkId,bool isSupport)249 void DSchedAllConnectManager::NotifyAllConnectDecision(const std::string &peerNetworkId, bool isSupport)
250 {
251     HILOGI("Notify all connect decision, peerNetworkId %{public}s, isSupport %{public}d.",
252         GetAnonymStr(peerNetworkId).c_str(), isSupport);
253     std::lock_guard<std::mutex> decisionLock(connectDecisionMutex_);
254     peerConnectDecision_[peerNetworkId] = isSupport;
255     connectDecisionCond_.notify_all();
256 }
257 
GetResourceRequest(ServiceCollaborationManager_ResourceRequestInfoSets & reqInfoSets)258 void DSchedAllConnectManager::GetResourceRequest(ServiceCollaborationManager_ResourceRequestInfoSets &reqInfoSets)
259 {
260     reqInfoSets.remoteHardwareListSize = 1;
261     reqInfoSets.remoteHardwareList = &rmtReqInfo_;
262     reqInfoSets.localHardwareListSize = 1;
263     reqInfoSets.localHardwareList = &locReqInfo_;
264     reqInfoSets.communicationRequest = &communicationRequest_;
265 }
266 
OnStop(const char * peerNetworkId)267 int32_t DSchedAllConnectManager::OnStop(const char *peerNetworkId)
268 {
269     HILOGI("OnStop, when other task prepare to seize bind, disconnect DMS bind with peerNetworkId %{public}s.",
270         GetAnonymStr(peerNetworkId).c_str());
271     int32_t sessionId = -1;
272     if (!DSchedTransportSoftbusAdapter::GetInstance().GetSessionIdByDeviceId(peerNetworkId, sessionId)) {
273         HILOGW("Not find any sessionId by peerNetworkId %{public}s.", GetAnonymStr(peerNetworkId).c_str());
274         return ERR_OK;
275     }
276     DSchedTransportSoftbusAdapter::GetInstance().OnShutdown(sessionId, false);
277     return ERR_OK;
278 }
279 
ApplyResult(int32_t errorcode,int32_t result,const char * reason)280 int32_t DSchedAllConnectManager::ApplyResult(int32_t errorcode, int32_t result, const char *reason)
281 {
282     HILOGI("Apply result start, errorcode %{public}d, result %{public}s, reason %{public}s.",
283         errorcode, result == ServiceCollaborationManagerResultCode::PASS ? "PASS" : "REJECT", reason);
284 
285     bool isSupport = result == ServiceCollaborationManagerResultCode::PASS ? true : false;
286     if (peerConnectCbQueue_.empty()) {
287         HILOGE("Apply result start, peerConnectCbQueue is empty.");
288         return ERR_OK;
289     }
290     std::string peerNetworkId = peerConnectCbQueue_.front();
291     DSchedAllConnectManager::GetInstance().NotifyAllConnectDecision(peerNetworkId, isSupport);
292     peerConnectCbQueue_.pop();
293     return ERR_OK;
294 }
295 } // namespace DistributedSchedule
296 } // namespace OHOS