1 /*
2 * Copyright (c) 2021 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 "component_manager.h"
17
18 #include <future>
19 #include <string>
20
21 #include "anonymous_string.h"
22 #include "capability_info_manager.h"
23 #include "component_disable.h"
24 #include "component_enable.h"
25 #include "component_loader.h"
26 #include "constants.h"
27 #include "dh_context.h"
28 #include "dh_utils_tool.h"
29 #include "distributed_hardware_errno.h"
30 #include "distributed_hardware_log.h"
31 #include "ipc_object_stub.h"
32 #include "iservice_registry.h"
33 #include "system_ability_definition.h"
34 #include "version_manager.h"
35
36 namespace OHOS {
37 namespace DistributedHardware {
38 #undef DH_LOG_TAG
39 #define DH_LOG_TAG "ComponentManager"
40
41 IMPLEMENT_SINGLE_INSTANCE(ComponentManager);
42
43 namespace {
44 constexpr int32_t ENABLE_RETRY_MAX_TIMES = 30;
45 constexpr int32_t DISABLE_RETRY_MAX_TIMES = 30;
46 constexpr int32_t ENABLE_PARAM_RETRY_TIME = 500 * 1000;
47 }
48
~ComponentManager()49 ComponentManager::~ComponentManager()
50 {
51 DHLOGD("start.");
52 }
53
Init()54 int32_t ComponentManager::Init()
55 {
56 DHLOGI("start.");
57 if (!InitCompSource()) {
58 DHLOGE("InitCompSource failed.");
59 return ERR_DH_FWK_COMPONENT_INIT_SOURCE_FAILED;
60 }
61 if (!InitCompSink()) {
62 DHLOGE("InitCompSink failed.");
63 compSource_.clear();
64 return ERR_DH_FWK_COMPONENT_INIT_SINK_FAILED;
65 }
66
67 auto sourceResult = StartSource();
68 auto sinkResult = StartSink();
69
70 if (!WaitForResult(Action::START_SOURCE, sourceResult)) {
71 DHLOGE("StartSource failed, some virtual components maybe cannot work, but want to continue");
72 }
73 if (!WaitForResult(Action::START_SINK, sinkResult)) {
74 DHLOGE("StartSink failed, some virtual components maybe cannot work, but want to continue");
75 }
76
77 DHLOGI("Init component success");
78
79 return DH_FWK_SUCCESS;
80 }
81
UnInit()82 int32_t ComponentManager::UnInit()
83 {
84 DHLOGI("start.");
85 auto sourceResult = StopSource();
86 auto sinkResult = StopSink();
87
88 if (!WaitForResult(Action::STOP_SOURCE, sourceResult)) {
89 DHLOGE("StopSource failed, but want to continue");
90 }
91 if (!WaitForResult(Action::STOP_SINK, sinkResult)) {
92 DHLOGE("StopSource failed, but want to continue");
93 }
94
95 compSource_.clear();
96 compSink_.clear();
97 {
98 std::lock_guard<std::mutex> lock(sinkVersionMutex_);
99 sinkVersions_.clear();
100 }
101 DHLOGI("Release component success");
102 return DH_FWK_SUCCESS;
103 }
104
StartSource()105 ComponentManager::ActionResult ComponentManager::StartSource()
106 {
107 DHLOGI("start.");
108 std::unordered_map<DHType, std::shared_future<int32_t>> futures;
109 std::string uuid = DHContext::GetInstance().GetDeviceInfo().uuid;
110 for (const auto &item : compSource_) {
111 CompVersion compversion;
112 VersionManager::GetInstance().GetCompVersion(uuid, item.first, compversion);
113 auto params = compversion.sourceVersion;
114 auto future = std::async(std::launch::async, [item, params]() { return item.second->InitSource(params); });
115 futures.emplace(item.first, future.share());
116 }
117 return futures;
118 }
119
StartSink()120 ComponentManager::ActionResult ComponentManager::StartSink()
121 {
122 DHLOGI("start.");
123 std::unordered_map<DHType, std::shared_future<int32_t>> futures;
124 std::string uuid = DHContext::GetInstance().GetDeviceInfo().uuid;
125 for (const auto &item : compSink_) {
126 CompVersion compversion;
127 VersionManager::GetInstance().GetCompVersion(uuid, item.first, compversion);
128 auto params = compversion.sinkVersion;
129 auto future = std::async(std::launch::async, [item, params]() { return item.second->InitSink(params); });
130 futures.emplace(item.first, future.share());
131 }
132 return futures;
133 }
134
StopSource()135 ComponentManager::ActionResult ComponentManager::StopSource()
136 {
137 DHLOGI("start.");
138 std::unordered_map<DHType, std::shared_future<int32_t>> futures;
139 for (const auto &item : compSource_) {
140 auto future = std::async(std::launch::async, [item]() { return item.second->ReleaseSource(); });
141 futures.emplace(item.first, future.share());
142 }
143 return futures;
144 }
145
StopSink()146 ComponentManager::ActionResult ComponentManager::StopSink()
147 {
148 DHLOGI("start.");
149 std::unordered_map<DHType, std::shared_future<int32_t>> futures;
150 for (const auto &item : compSink_) {
151 auto future = std::async(std::launch::async, [item]() { return item.second->ReleaseSink(); });
152 futures.emplace(item.first, future.share());
153 }
154 return futures;
155 }
156
WaitForResult(const Action & action,ActionResult actionsResult)157 bool ComponentManager::WaitForResult(const Action &action, ActionResult actionsResult)
158 {
159 DHLOGD("start.");
160 auto ret = true;
161 for (auto &iter : actionsResult) {
162 auto result = iter.second.get();
163 DHLOGI("action = %d, compType = %#X, ret = %d.", static_cast<int32_t>(action), iter.first, result);
164 if (result != DH_FWK_SUCCESS) {
165 ret = false;
166 DHLOGE("there is error, but want to continue.");
167 }
168 }
169 DHLOGD("end.");
170 return ret;
171 }
172
InitCompSource()173 bool ComponentManager::InitCompSource()
174 {
175 auto compTypes = ComponentLoader::GetInstance().GetAllCompTypes();
176 for (const auto &type : compTypes) {
177 IDistributedHardwareSource *sourcePtr = nullptr;
178 auto ret = ComponentLoader::GetInstance().GetSource(type, sourcePtr);
179 if (ret != DH_FWK_SUCCESS) {
180 DHLOGW("GetSource failed, compType = %#X, ret = %d.", type, ret);
181 continue;
182 }
183 if (sourcePtr == nullptr) {
184 DHLOGW("sourcePtr is null, compType = %#X.", type);
185 continue;
186 }
187 compSource_.insert(std::make_pair(type, sourcePtr));
188 }
189 return !compSource_.empty();
190 }
191
InitCompSink()192 bool ComponentManager::InitCompSink()
193 {
194 auto compTypes = ComponentLoader::GetInstance().GetAllCompTypes();
195 for (const auto &type : compTypes) {
196 IDistributedHardwareSink *sinkPtr = nullptr;
197 auto ret = ComponentLoader::GetInstance().GetSink(type, sinkPtr);
198 if (ret != DH_FWK_SUCCESS) {
199 DHLOGW("GetSink failed, compType = %#X, ret = %d.", type, ret);
200 continue;
201 }
202 if (sinkPtr == nullptr) {
203 DHLOGW("sinkPtr is null, compType = %#X.", type);
204 continue;
205 }
206 compSink_.insert(std::make_pair(type, sinkPtr));
207 }
208 return !compSink_.empty();
209 }
210
Enable(const std::string & networkId,const std::string & uuid,const std::string & dhId)211 int32_t ComponentManager::Enable(const std::string &networkId, const std::string &uuid, const std::string &dhId)
212 {
213 DHLOGI("start.");
214 auto dhType = GetDHType(uuid, dhId);
215 auto find = compSource_.find(dhType);
216 if (find == compSource_.end()) {
217 DHLOGE("can not find handler for dhId = %s.", dhId.c_str());
218 return ERR_DH_FWK_PARA_INVALID;
219 }
220 EnableParam param;
221 auto ret = GetEnableParam(networkId, uuid, dhId, dhType, param);
222 if (ret != DH_FWK_SUCCESS) {
223 DHLOGE("GetEnableParam failed, uuid = %s, dhId = %s, errCode = %d", GetAnonyString(uuid).c_str(),
224 dhId.c_str(), ret);
225 for (int32_t retryCount = 0; retryCount < ENABLE_RETRY_MAX_TIMES; retryCount++) {
226 if (!DHContext::GetInstance().IsDeviceOnline(uuid)) {
227 DHLOGE("device is already offline, no need try GetEnableParam, uuid = %s",
228 GetAnonyString(uuid).c_str());
229 return ret;
230 }
231 if (GetEnableParam(networkId, uuid, dhId, dhType, param) == DH_FWK_SUCCESS) {
232 DHLOGE("GetEnableParam success, retryCount = %d", retryCount);
233 break;
234 }
235 DHLOGE("GetEnableParam failed, retryCount = %d", retryCount);
236 usleep(ENABLE_PARAM_RETRY_TIME);
237 }
238 }
239 auto compEnable = std::make_shared<ComponentEnable>();
240 auto result = compEnable->Enable(networkId, dhId, param, find->second);
241 if (result != DH_FWK_SUCCESS) {
242 for (int32_t retryCount = 0; retryCount < ENABLE_RETRY_MAX_TIMES; retryCount++) {
243 if (!DHContext::GetInstance().IsDeviceOnline(uuid)) {
244 DHLOGE("device is already offline, no need try enable, uuid = %s", GetAnonyString(uuid).c_str());
245 return result;
246 }
247 if (compEnable->Enable(networkId, dhId, param, find->second) == DH_FWK_SUCCESS) {
248 DHLOGE("enable success, retryCount = %d", retryCount);
249 return DH_FWK_SUCCESS;
250 }
251 DHLOGE("enable failed, retryCount = %d", retryCount);
252 }
253 return result;
254 }
255 DHLOGI("enable result is %d, uuid = %s, dhId = %s", result, GetAnonyString(uuid).c_str(), dhId.c_str());
256 return result;
257 }
258
Disable(const std::string & networkId,const std::string & uuid,const std::string & dhId)259 int32_t ComponentManager::Disable(const std::string &networkId, const std::string &uuid, const std::string &dhId)
260 {
261 auto dhType = GetDHType(uuid, dhId);
262 auto find = compSource_.find(dhType);
263 if (find == compSource_.end()) {
264 DHLOGE("can not find handler for dhId = %s.", dhId.c_str());
265 return ERR_DH_FWK_PARA_INVALID;
266 }
267 auto compDisable = std::make_shared<ComponentDisable>();
268 auto result = compDisable->Disable(networkId, dhId, find->second);
269 if (result != DH_FWK_SUCCESS) {
270 for (int32_t retryCount = 0; retryCount < DISABLE_RETRY_MAX_TIMES; retryCount++) {
271 if (DHContext::GetInstance().IsDeviceOnline(uuid)) {
272 DHLOGE("device is already online, no need try disable, uuid = %s", GetAnonyString(uuid).c_str());
273 return result;
274 }
275 if (compDisable->Disable(networkId, dhId, find->second) == DH_FWK_SUCCESS) {
276 DHLOGE("disable success, retryCount = %d", retryCount);
277 return DH_FWK_SUCCESS;
278 }
279 DHLOGE("disable failed, retryCount = %d", retryCount);
280 }
281 return result;
282 }
283 DHLOGI("disable result is %d, uuid = %s, dhId = %s", result, GetAnonyString(uuid).c_str(), dhId.c_str());
284 return result;
285 }
286
GetDHType(const std::string & uuid,const std::string & dhId) const287 DHType ComponentManager::GetDHType(const std::string &uuid, const std::string &dhId) const
288 {
289 std::shared_ptr<CapabilityInfo> capability = nullptr;
290 auto ret = CapabilityInfoManager::GetInstance()->GetCapability(GetDeviceIdByUUID(uuid), dhId, capability);
291 if ((ret == DH_FWK_SUCCESS) && (capability != nullptr)) {
292 return capability->GetDHType();
293 }
294 DHLOGE("get dhType failed, uuid = %s, dhId = %s", GetAnonyString(uuid).c_str(), dhId.c_str());
295 return DHType::UNKNOWN;
296 }
297
GetEnableParam(const std::string & networkId,const std::string & uuid,const std::string & dhId,DHType dhType,EnableParam & param)298 int32_t ComponentManager::GetEnableParam(const std::string &networkId, const std::string &uuid,
299 const std::string &dhId, DHType dhType, EnableParam ¶m)
300 {
301 std::shared_ptr<CapabilityInfo> capability = nullptr;
302 auto ret = CapabilityInfoManager::GetInstance()->GetCapability(GetDeviceIdByUUID(uuid), dhId, capability);
303 if ((ret != DH_FWK_SUCCESS) || (capability == nullptr)) {
304 DHLOGE("GetCapability failed, uuid =%s, dhId = %s, errCode = %d", GetAnonyString(uuid).c_str(), dhId.c_str(),
305 ret);
306 return ret;
307 }
308
309 param.attrs = capability->GetDHAttrs();
310 param.version = GetSinkVersion(networkId, uuid, dhType);
311 if (param.version.empty()) {
312 DHLOGI("Get Sink Version failed, uuid = %s, dhId = %s", GetAnonyString(uuid).c_str(), dhId.c_str());
313 return ERR_DH_FWK_COMPONENT_GET_SINK_VERSION_FAILED;
314 }
315
316 DHLOGI("success. uuid =%s, dhId = %s, version = %s", GetAnonyString(uuid).c_str(), dhId.c_str(),
317 param.version.c_str());
318
319 return DH_FWK_SUCCESS;
320 }
321
GetSinkVersion(const std::string & networkId,const std::string & uuid,DHType dhType)322 std::string ComponentManager::GetSinkVersion(const std::string &networkId, const std::string &uuid, DHType dhType)
323 {
324 DHLOGI("networkId = %s ", GetAnonyString(networkId).c_str());
325 auto sinkVersion = GetVersionFromCache(uuid, dhType);
326 if (!sinkVersion.empty()) {
327 DHLOGI("GetVersionFromCache success, sinkVersion = %s, uuid = %s, dhType = %#X", sinkVersion.c_str(),
328 GetAnonyString(uuid).c_str(), dhType);
329 return sinkVersion;
330 }
331
332 auto updateResult = UpdateVersionCache(networkId, uuid);
333 if (updateResult != DH_FWK_SUCCESS) {
334 DHLOGE("UpdateVersionCache failed, uuid = %s, errCode = %d", GetAnonyString(uuid).c_str(), updateResult);
335 return "";
336 }
337
338 sinkVersion = GetVersionFromCache(uuid, dhType);
339 return sinkVersion;
340 }
341
GetVersionFromCache(const std::string & uuid,DHType dhType)342 std::string ComponentManager::GetVersionFromCache(const std::string &uuid, DHType dhType)
343 {
344 std::lock_guard<std::mutex> lock(sinkVersionMutex_);
345 auto iter = sinkVersions_.find(uuid);
346 if (iter == sinkVersions_.end()) {
347 DHLOGE("can not find component version for uuid = %s", GetAnonyString(uuid).c_str());
348 return "";
349 }
350
351 auto find = iter->second.find(dhType);
352 if (find == iter->second.end()) {
353 DHLOGE("can not find component version for uuid = %s, dhType = %#X", uuid.c_str(), dhType);
354 return "";
355 }
356 return find->second;
357 }
358
UpdateVersionCache(const std::string & networkId,const std::string & uuid)359 int32_t ComponentManager::UpdateVersionCache(const std::string &networkId, const std::string &uuid)
360 {
361 sptr<IDistributedHardware> dhms = GetRemoteDHMS(networkId);
362 if (dhms == nullptr) {
363 DHLOGI("GetRemoteDHMS failed, networkId = %s", GetAnonyString(networkId).c_str());
364 return ERR_DH_FWK_COMPONENT_GET_REMOTE_SA_FAILED;
365 }
366
367 std::unordered_map<DHType, std::string> versions;
368 auto ret = dhms->QuerySinkVersion(versions);
369 if (ret != DH_FWK_SUCCESS) {
370 DHLOGE("QuerySinkVersion failed, errCode = %d", ret);
371 return ret;
372 }
373 {
374 std::lock_guard<std::mutex> lock(sinkVersionMutex_);
375 sinkVersions_.emplace(uuid, versions);
376 }
377 DHLOGI("QuerySinkVersion success");
378 return DH_FWK_SUCCESS;
379 }
380
GetRemoteDHMS(const std::string & networkId) const381 sptr<IDistributedHardware> ComponentManager::GetRemoteDHMS(const std::string &networkId) const
382 {
383 DHLOGI("start, networkId = %s", GetAnonyString(networkId).c_str());
384 if (networkId.empty()) {
385 DHLOGE("networkId is empty");
386 return nullptr;
387 }
388 auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
389 if (samgr == nullptr) {
390 DHLOGE("GetSystemAbilityManager failed");
391 return nullptr;
392 }
393 auto object = samgr->CheckSystemAbility(DISTRIBUTED_HARDWARE_SA_ID, networkId);
394 if (object == nullptr) {
395 DHLOGE("CheckSystemAbility failed");
396 return nullptr;
397 }
398 return iface_cast<IDistributedHardware>(object);
399 }
400 }
401 }
402