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