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