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