1 /*
2 * Copyright (c) 2021-2025 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 "offline_task.h"
17
18 #include <pthread.h>
19 #include <thread>
20
21 #include "ffrt.h"
22
23 #include "anonymous_string.h"
24 #include "capability_info_manager.h"
25 #include "dh_context.h"
26 #include "dh_utils_tool.h"
27 #include "distributed_hardware_errno.h"
28 #include "distributed_hardware_log.h"
29 #include "distributed_hardware_manager_factory.h"
30 #include "meta_info_manager.h"
31 #include "task_board.h"
32 #include "task_executor.h"
33 #include "task_factory.h"
34
35 namespace OHOS {
36 namespace DistributedHardware {
37 namespace {
38 constexpr uint16_t PHONE_TYPE = 14;
39 constexpr const char *OFFLINE_TASK_INNER = "OffLineTask";
40 }
41 #undef DH_LOG_TAG
42 #define DH_LOG_TAG "OffLineTask"
43
OffLineTask(const std::string & networkId,const std::string & uuid,const std::string & udid,const std::string & dhId,const DHType dhType)44 OffLineTask::OffLineTask(const std::string &networkId, const std::string &uuid, const std::string &udid,
45 const std::string &dhId, const DHType dhType) : Task(networkId, uuid, udid, dhId, dhType)
46 {
47 this->SetTaskType(TaskType::OFF_LINE);
48 this->SetTaskSteps({TaskStep::META_DISABLE_TASK, TaskStep::UNREGISTER_OFFLINE_DISTRIBUTED_HARDWARE,
49 TaskStep::DISABLE_SINK, TaskStep::WAIT_UNREGISTGER_COMPLETE, TaskStep::CLEAR_OFFLINE_INFO});
50 DHLOGD("OffLineTask id: %{public}s, networkId: %{public}s, uuid: %{public}s, udid: %{public}s",
51 GetId().c_str(), GetAnonyString(GetNetworkId()).c_str(), GetAnonyString(GetUUID()).c_str(),
52 GetAnonyString(GetUDID()).c_str());
53 }
54
~OffLineTask()55 OffLineTask::~OffLineTask()
56 {
57 DHLOGD("id = %{public}s, uuid = %{public}s", GetId().c_str(), GetAnonyString(GetUUID()).c_str());
58 }
59
DoTask()60 void OffLineTask::DoTask()
61 {
62 ffrt::submit([this]() { this->DoTaskInner(); });
63 }
64
DoTaskInner()65 void OffLineTask::DoTaskInner()
66 {
67 int32_t ret = pthread_setname_np(pthread_self(), OFFLINE_TASK_INNER);
68 if (ret != DH_FWK_SUCCESS) {
69 DHLOGE("DoTaskInner setname failed.");
70 }
71 DHLOGD("start offline task, id = %{public}s, uuid = %{public}s", GetId().c_str(),
72 GetAnonyString(GetUUID()).c_str());
73 this->SetTaskState(TaskState::RUNNING);
74 for (const auto& step : this->GetTaskSteps()) {
75 switch (step) {
76 case TaskStep::UNREGISTER_OFFLINE_DISTRIBUTED_HARDWARE: {
77 CreateDisableTask();
78 break;
79 }
80 case TaskStep::DISABLE_SINK: {
81 CreateDisableSinkTask();
82 break;
83 }
84 case TaskStep::WAIT_UNREGISTGER_COMPLETE: {
85 WaitDisableTaskFinish();
86 break;
87 }
88 case TaskStep::CLEAR_OFFLINE_INFO: {
89 ClearOffLineInfo();
90 break;
91 }
92 case TaskStep::META_DISABLE_TASK: {
93 CreateMetaDisableTask();
94 break;
95 }
96 default: {
97 break;
98 }
99 }
100 }
101
102 this->SetTaskState(TaskState::SUCCESS);
103 DHLOGI("Finish OffLine task, remove it, id: %{public}s", GetId().c_str());
104 TaskBoard::GetInstance().RemoveTask(this->GetId());
105 if (DHContext::GetInstance().GetRealTimeOnlineDeviceCount() == 0 &&
106 DHContext::GetInstance().GetIsomerismConnectCount() == 0 &&
107 TaskBoard::GetInstance().IsAllDisableTaskFinish()) {
108 DHLOGI("all devices are offline and all disable tasks are finished, start to free the resource");
109 DistributedHardwareManagerFactory::GetInstance().UnInit();
110 }
111 }
112
CreateDisableTask()113 void OffLineTask::CreateDisableTask()
114 {
115 DHLOGI("networkId = %{public}s, uuid = %{public}s", GetAnonyString(GetNetworkId()).c_str(),
116 GetAnonyString(GetUUID()).c_str());
117 std::string deviceId = GetDeviceIdByUUID(GetUUID());
118 std::vector<std::pair<std::string, DHType>> devDhInfos;
119 std::vector<std::shared_ptr<CapabilityInfo>> capabilityInfos;
120 CapabilityInfoManager::GetInstance()->GetCapabilitiesByDeviceId(deviceId, capabilityInfos);
121 std::for_each(capabilityInfos.begin(), capabilityInfos.end(), [&](std::shared_ptr<CapabilityInfo> cap) {
122 if (cap != nullptr) {
123 devDhInfos.push_back({cap->GetDHId(), cap->GetDHType()});
124 }
125 });
126
127 if (devDhInfos.empty()) {
128 DHLOGW("Can not get cap info from CapabilityInfo, try use meta info");
129 std::vector<std::shared_ptr<MetaCapabilityInfo>> metaCapInfos;
130 std::string udidHash = DHContext::GetInstance().GetUdidHashIdByUUID(GetUUID());
131 MetaInfoManager::GetInstance()->GetMetaCapInfosByUdidHash(udidHash, metaCapInfos);
132 std::for_each(metaCapInfos.begin(), metaCapInfos.end(), [&](std::shared_ptr<MetaCapabilityInfo> cap) {
133 if (cap != nullptr) {
134 devDhInfos.push_back({cap->GetDHId(), cap->GetDHType()});
135 }
136 });
137 }
138
139 if (devDhInfos.empty()) {
140 DHLOGE("Can not get cap info, uuid = %{public}s, deviceId = %{public}s", GetAnonyString(GetUUID()).c_str(),
141 GetAnonyString(deviceId).c_str());
142 return;
143 }
144
145 for (const auto &info : devDhInfos) {
146 TaskParam taskParam = {
147 .networkId = GetNetworkId(),
148 .uuid = GetUUID(),
149 .dhId = info.first,
150 .dhType = info.second
151 };
152 auto task = TaskFactory::GetInstance().CreateTask(TaskType::DISABLE, taskParam, shared_from_this());
153 TaskExecutor::GetInstance().PushTask(task);
154 }
155 }
156
CreateDisableSinkTask()157 void OffLineTask::CreateDisableSinkTask()
158 {
159 DHLOGI("CreateDisableSinkTask start");
160 DeviceInfo localDeviceInfo = GetLocalDeviceInfo();
161 std::vector<std::pair<std::string, DHType>> localMetaInfos;
162 std::vector<std::shared_ptr<MetaCapabilityInfo>> metaCapInfos;
163 MetaInfoManager::GetInstance()->GetMetaCapInfosByUdidHash(localDeviceInfo.udidHash, metaCapInfos);
164 std::for_each(metaCapInfos.begin(), metaCapInfos.end(), [&](std::shared_ptr<MetaCapabilityInfo> localMetaInfo) {
165 if (localMetaInfo != nullptr) {
166 localMetaInfos.push_back({localMetaInfo->GetDHId(), localMetaInfo->GetDHType()});
167 }
168 });
169 if (localMetaInfos.empty()) {
170 DHLOGE("Can not get localMetainfo.");
171 return;
172 }
173 for (const auto &localInfo : localMetaInfos) {
174 TaskParam taskParam = {
175 .networkId = localDeviceInfo.networkId,
176 .uuid = localDeviceInfo.uuid,
177 .udid = localDeviceInfo.udid,
178 .dhId = localInfo.first,
179 .dhType = localInfo.second
180 };
181 auto task = TaskFactory::GetInstance().CreateTask(TaskType::DISABLE, taskParam, shared_from_this());
182 TaskExecutor::GetInstance().PushTask(task);
183 }
184 }
185
WaitDisableTaskFinish()186 void OffLineTask::WaitDisableTaskFinish()
187 {
188 DHLOGI("start wait disable task finish");
189 std::unique_lock<std::mutex> waitLock(unFinishTaskMtx_);
190 finishCondVar_.wait(waitLock, [&] { return this->unFinishChildrenTasks_.empty(); });
191 DHLOGI("all disable task finish");
192 DHContext::GetInstance().RemoveOnlineDeviceIdEntryByNetworkId(GetNetworkId());
193 }
194
ClearOffLineInfo()195 void OffLineTask::ClearOffLineInfo()
196 {
197 DHLOGI("start clear resource when device offline, uuid = %{public}s", GetAnonyString(GetUUID()).c_str());
198 auto ret = CapabilityInfoManager::GetInstance()->RemoveCapabilityInfoInMem(GetDeviceIdByUUID(GetUUID()));
199 if (ret != DH_FWK_SUCCESS) {
200 DHLOGE("RemoveCapabilityInfoInMem failed, uuid = %{public}s, errCode = %{public}d",
201 GetAnonyString(GetUUID()).c_str(), ret);
202 }
203 }
204
NotifyFatherFinish(std::string taskId)205 void OffLineTask::NotifyFatherFinish(std::string taskId)
206 {
207 {
208 std::lock_guard<std::mutex> lock(unFinishTaskMtx_);
209 this->unFinishChildrenTasks_.erase(taskId);
210 }
211 finishCondVar_.notify_all();
212 }
213
AddChildrenTask(std::shared_ptr<Task> childrenTask)214 void OffLineTask::AddChildrenTask(std::shared_ptr<Task> childrenTask)
215 {
216 std::lock_guard<std::mutex> lock(unFinishTaskMtx_);
217 this->unFinishChildrenTasks_.insert(childrenTask->GetId());
218 }
219
CreateMetaDisableTask()220 void OffLineTask::CreateMetaDisableTask()
221 {
222 DHLOGI("CreateMetaDisableTask, networkId = %{public}s, uuid = %{public}s", GetAnonyString(GetNetworkId()).c_str(),
223 GetAnonyString(GetUUID()).c_str());
224 uint16_t deviceType = DHContext::GetInstance().GetDeviceTypeByNetworkId(GetNetworkId());
225 if (deviceType != PHONE_TYPE) {
226 DHLOGI("offline device not phone, deviceType = %{public}d", deviceType);
227 return;
228 }
229 TaskParam taskParam = {
230 .networkId = GetNetworkId(),
231 .uuid = GetUUID(),
232 .dhId = "Modem_1234",
233 .dhType = DHType::MODEM
234 };
235 auto task = TaskFactory::GetInstance().CreateTask(TaskType::META_DISABLE, taskParam, shared_from_this());
236 TaskExecutor::GetInstance().PushTask(task);
237 }
238 } // namespace DistributedHardware
239 } // namespace OHOS
240