1 /*
2 * Copyright (c) 2021-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 "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 "constants.h"
26 #include "device_manager.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 "distributed_hardware_manager_factory.h"
32 #include "meta_info_manager.h"
33 #include "task_board.h"
34 #include "task_executor.h"
35 #include "task_factory.h"
36
37 namespace OHOS {
38 namespace DistributedHardware {
39 #undef DH_LOG_TAG
40 #define DH_LOG_TAG "OffLineTask"
41
OffLineTask(const std::string & networkId,const std::string & uuid,const std::string & udid,const std::string & dhId,const DHType dhType)42 OffLineTask::OffLineTask(const std::string &networkId, const std::string &uuid, const std::string &udid,
43 const std::string &dhId, const DHType dhType) : Task(networkId, uuid, udid, dhId, dhType)
44 {
45 this->SetTaskType(TaskType::OFF_LINE);
46 this->SetTaskSteps({TaskStep::META_DISABLE_TASK, TaskStep::UNREGISTER_OFFLINE_DISTRIBUTED_HARDWARE,
47 TaskStep::WAIT_UNREGISTGER_COMPLETE, TaskStep::CLEAR_OFFLINE_INFO});
48 DHLOGD("OffLineTask id: %{public}s, networkId: %{public}s, uuid: %{public}s, udid: %{public}s",
49 GetId().c_str(), GetAnonyString(GetNetworkId()).c_str(), GetAnonyString(GetUUID()).c_str(),
50 GetAnonyString(GetUDID()).c_str());
51 }
52
~OffLineTask()53 OffLineTask::~OffLineTask()
54 {
55 DHLOGD("id = %{public}s, uuid = %{public}s", GetId().c_str(), GetAnonyString(GetUUID()).c_str());
56 }
57
DoTask()58 void OffLineTask::DoTask()
59 {
60 ffrt::submit([this]() { this->DoTaskInner(); });
61 }
62
DoTaskInner()63 void OffLineTask::DoTaskInner()
64 {
65 int32_t ret = pthread_setname_np(pthread_self(), OFFLINE_TASK_INNER);
66 if (ret != DH_FWK_SUCCESS) {
67 DHLOGE("DoTaskInner setname failed.");
68 }
69 DHLOGD("start offline task, id = %{public}s, uuid = %{public}s", GetId().c_str(),
70 GetAnonyString(GetUUID()).c_str());
71 this->SetTaskState(TaskState::RUNNING);
72 for (const auto& step : this->GetTaskSteps()) {
73 switch (step) {
74 case TaskStep::UNREGISTER_OFFLINE_DISTRIBUTED_HARDWARE: {
75 CreateDisableTask();
76 break;
77 }
78 case TaskStep::WAIT_UNREGISTGER_COMPLETE: {
79 WaitDisableTaskFinish();
80 break;
81 }
82 case TaskStep::CLEAR_OFFLINE_INFO: {
83 ClearOffLineInfo();
84 break;
85 }
86 case TaskStep::META_DISABLE_TASK: {
87 CreateMetaDisableTask();
88 break;
89 }
90 default: {
91 break;
92 }
93 }
94 }
95
96 this->SetTaskState(TaskState::SUCCESS);
97 DHLOGD("Finish OffLine task, remove it, id: %{public}s", GetId().c_str());
98 TaskBoard::GetInstance().RemoveTask(this->GetId());
99 if (DHContext::GetInstance().GetRealTimeOnlineDeviceCount() == 0 &&
100 DHContext::GetInstance().GetIsomerismConnectCount() == 0 &&
101 TaskBoard::GetInstance().IsAllTaskFinish()) {
102 DHLOGI("all devices are offline, start to free the resource");
103 DistributedHardwareManagerFactory::GetInstance().UnInit();
104 }
105 }
106
CreateDisableTask()107 void OffLineTask::CreateDisableTask()
108 {
109 DHLOGI("networkId = %{public}s, uuid = %{public}s", GetAnonyString(GetNetworkId()).c_str(),
110 GetAnonyString(GetUUID()).c_str());
111 std::string deviceId = GetDeviceIdByUUID(GetUUID());
112 std::vector<std::pair<std::string, DHType>> devDhInfos;
113 std::vector<std::shared_ptr<CapabilityInfo>> capabilityInfos;
114 CapabilityInfoManager::GetInstance()->GetCapabilitiesByDeviceId(deviceId, capabilityInfos);
115 std::for_each(capabilityInfos.begin(), capabilityInfos.end(), [&](std::shared_ptr<CapabilityInfo> cap) {
116 devDhInfos.push_back({cap->GetDHId(), cap->GetDHType()});
117 });
118
119 if (devDhInfos.empty()) {
120 DHLOGW("Can not get cap info from CapabilityInfo, try use meta info");
121 std::vector<std::shared_ptr<MetaCapabilityInfo>> metaCapInfos;
122 std::string udidHash = DHContext::GetInstance().GetUdidHashIdByUUID(GetUUID());
123 MetaInfoManager::GetInstance()->GetMetaCapInfosByUdidHash(udidHash, metaCapInfos);
124 std::for_each(metaCapInfos.begin(), metaCapInfos.end(), [&](std::shared_ptr<MetaCapabilityInfo> cap) {
125 devDhInfos.push_back({cap->GetDHId(), cap->GetDHType()});
126 });
127 }
128
129 if (devDhInfos.empty()) {
130 DHLOGE("Can not get cap info, uuid = %{public}s, deviceId = %{public}s", GetAnonyString(GetUUID()).c_str(),
131 GetAnonyString(deviceId).c_str());
132 }
133
134 for (const auto &info : devDhInfos) {
135 TaskParam taskParam = {
136 .networkId = GetNetworkId(),
137 .uuid = GetUUID(),
138 .dhId = info.first,
139 .dhType = info.second
140 };
141 auto task = TaskFactory::GetInstance().CreateTask(TaskType::DISABLE, taskParam, shared_from_this());
142 TaskExecutor::GetInstance().PushTask(task);
143 }
144 }
145
WaitDisableTaskFinish()146 void OffLineTask::WaitDisableTaskFinish()
147 {
148 DHLOGI("start wait disable task finish");
149 std::unique_lock<std::mutex> waitLock(unFinishTaskMtx_);
150 finishCondVar_.wait(waitLock, [&] { return this->unFinishChildrenTasks_.empty(); });
151 DHLOGI("all disable task finish");
152 DHContext::GetInstance().RemoveOnlineDeviceIdEntryByNetworkId(GetNetworkId());
153 }
154
ClearOffLineInfo()155 void OffLineTask::ClearOffLineInfo()
156 {
157 DHLOGI("start clear resource when device offline, uuid = %{public}s", GetAnonyString(GetUUID()).c_str());
158 auto ret = CapabilityInfoManager::GetInstance()->RemoveCapabilityInfoInMem(GetDeviceIdByUUID(GetUUID()));
159 if (ret != DH_FWK_SUCCESS) {
160 DHLOGE("RemoveCapabilityInfoInMem failed, uuid = %{public}s, errCode = %{public}d",
161 GetAnonyString(GetUUID()).c_str(), ret);
162 }
163 }
164
NotifyFatherFinish(std::string taskId)165 void OffLineTask::NotifyFatherFinish(std::string taskId)
166 {
167 {
168 std::lock_guard<std::mutex> lock(unFinishTaskMtx_);
169 this->unFinishChildrenTasks_.erase(taskId);
170 }
171 finishCondVar_.notify_all();
172 }
173
AddChildrenTask(std::shared_ptr<Task> childrenTask)174 void OffLineTask::AddChildrenTask(std::shared_ptr<Task> childrenTask)
175 {
176 std::lock_guard<std::mutex> lock(unFinishTaskMtx_);
177 this->unFinishChildrenTasks_.insert(childrenTask->GetId());
178 }
179
CreateMetaDisableTask()180 void OffLineTask::CreateMetaDisableTask()
181 {
182 DHLOGI("CreateMetaDisableTask, networkId = %{public}s, uuid = %{public}s", GetAnonyString(GetNetworkId()).c_str(),
183 GetAnonyString(GetUUID()).c_str());
184 int32_t deviceType = DmDeviceType::DEVICE_TYPE_UNKNOWN;
185 DeviceManager::GetInstance().GetDeviceType(DH_FWK_PKG_NAME, GetNetworkId(), deviceType);
186 if (deviceType != DmDeviceType::DEVICE_TYPE_PHONE) {
187 DHLOGI("CreateMetaDisableTask, offline device not phone, deviceType = %{public}d", deviceType);
188 return;
189 }
190 TaskParam taskParam = {
191 .networkId = GetNetworkId(),
192 .uuid = GetUUID(),
193 .dhId = GetDhId(),
194 .dhType = GetDhType()
195 };
196 auto task = TaskFactory::GetInstance().CreateTask(TaskType::META_DISABLE, taskParam, shared_from_this());
197 TaskExecutor::GetInstance().PushTask(task);
198 }
199 } // namespace DistributedHardware
200 } // namespace OHOS
201