• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023-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 <limits>
17 
18 #include "form_status_queue.h"
19 #include "fms_log_wrapper.h"
20 #include "form_mgr_errors.h"
21 #include "form_host_interface.h"
22 
23 namespace OHOS {
24 namespace AppExecFwk {
25 using namespace ffrt;
26 namespace {
27 constexpr uint32_t CONVERSION_FACTOR = 1000; // ms to us
28 const std::string FORM_STATUS_QUEUE = "FormStatusQueue";
29 }
30 
FormStatusQueue()31 FormStatusQueue::FormStatusQueue(): queue_(FORM_STATUS_QUEUE.c_str())
32 {
33     HILOG_DEBUG("create FormStatusQueue, queueName :%{public}s", FORM_STATUS_QUEUE.c_str());
34 }
35 
~FormStatusQueue()36 FormStatusQueue::~FormStatusQueue()
37 {
38     HILOG_DEBUG("destroy FormStatusQueue");
39 }
40 
ScheduleTask(uint64_t ms,std::function<void ()> func)41 bool FormStatusQueue::ScheduleTask(uint64_t ms, std::function<void()> func)
42 {
43     HILOG_DEBUG("begin to ScheduleTask");
44     if (ms > (std::numeric_limits<uint64_t>::max() / CONVERSION_FACTOR)) {
45         HILOG_ERROR("invalid ms,ScheduleTask failed");
46         return false;
47     }
48     std::unique_lock<std::shared_mutex> lock(mutex_);
49     task_handle task_handle = queue_.submit_h(func, task_attr().delay(ms * CONVERSION_FACTOR));
50     if (task_handle == nullptr) {
51         HILOG_ERROR("null task_handle");
52         return false;
53     }
54     HILOG_DEBUG("ScheduleTask success");
55     return true;
56 }
57 
ScheduleDelayTask(const std::pair<int64_t,int64_t> & eventMsg,uint32_t ms,std::function<void ()> func)58 void FormStatusQueue::ScheduleDelayTask(const std::pair<int64_t, int64_t> &eventMsg,
59     uint32_t ms, std::function<void()> func)
60 {
61     HILOG_DEBUG("begin to ScheduleDelayTask");
62     std::unique_lock<std::shared_mutex> lock(mutex_);
63     task_handle task_handle = queue_.submit_h(func, task_attr().delay(ms * CONVERSION_FACTOR));
64     if (task_handle == nullptr) {
65         HILOG_ERROR("null task_handle");
66         return;
67     }
68     taskMap_[eventMsg] = std::move(task_handle);
69     HILOG_DEBUG("ScheduleDelayTask success");
70 }
71 
CancelDelayTask(const std::pair<int64_t,int64_t> & eventMsg)72 void FormStatusQueue::CancelDelayTask(const std::pair<int64_t, int64_t> &eventMsg)
73 {
74     HILOG_DEBUG("begin to CancelDelayTask");
75     std::unique_lock<std::shared_mutex> lock(mutex_);
76     auto item = taskMap_.find(eventMsg);
77     if (item == taskMap_.end()) {
78         HILOG_ERROR("invalid task");
79         return;
80     }
81     if (item->second != nullptr) {
82         int32_t ret = queue_.cancel(item->second);
83         if (ret != 0) {
84             HILOG_ERROR("CancelDelayTask failed,errCode :%{public}d", ret);
85         }
86     }
87     taskMap_.erase(eventMsg);
88     HILOG_DEBUG("CancelDelayTask success");
89 }
90 
GetOrCreateFormStatusQueue(const int64_t formId,const sptr<IRemoteObject> & remoteObjectOfHost,FormStatus formStatus)91 std::shared_ptr<FormCommandQueue> FormStatusQueue::GetOrCreateFormStatusQueue(
92     const int64_t formId, const sptr<IRemoteObject> &remoteObjectOfHost, FormStatus formStatus)
93 {
94     std::unique_lock<std::shared_mutex> lock(formCommandQueueMapMutex_);
95     if (formCommandQueueMap_.find(formId) == formCommandQueueMap_.end()) {
96         std::shared_ptr<FormCommandQueue> formCommandQueue = std::make_shared<FormCommandQueue>(formId);
97         formCommandQueueMap_.emplace(std::make_pair(formId, formCommandQueue));
98         FormStatusMgr::GetInstance().AddFormStatus(formId, formStatus);
99         HILOG_INFO("formCommandQueueMap_ insert, formId:%{public}" PRId64 ". ", formId);
100     }
101 
102     if (formHostTokenMap_.find(formId) == formHostTokenMap_.end()) {
103         formHostTokenMap_.emplace(std::make_pair(formId, remoteObjectOfHost));
104         HILOG_INFO("formHostTokenMap_ insert, formId:%{public}" PRId64 ". ", formId);
105     }
106     return formCommandQueueMap_[formId];
107 }
108 
DeleteFormStatusQueueIfNecessary(const int64_t formId,const std::string compId)109 void FormStatusQueue::DeleteFormStatusQueueIfNecessary(const int64_t formId, const std::string compId)
110 {
111     std::unique_lock<std::shared_mutex> lock(formCommandQueueMapMutex_);
112     if (compId.empty() ||
113         formCommandQueueMap_.find(formId) == formCommandQueueMap_.end() ||
114         formCommandQueueMap_[formId]->IsCommondQueueEmpty()) {
115         formCommandQueueMap_.erase(formId);
116         formHostTokenMap_.erase(formId);
117         FormStatusMgr::GetInstance().DeleteFormStatus(formId);
118         HILOG_INFO("formCommandQueueMap_ erase, formId:%{public}" PRId64 ". ", formId);
119     }
120 }
121 
PostFormStatusTask(FormCommand formCommand,sptr<IRemoteObject> remoteObjectOfHost)122 void FormStatusQueue::PostFormStatusTask(FormCommand formCommand, sptr<IRemoteObject> remoteObjectOfHost)
123 {
124     auto formId = formCommand.getFormId();
125     auto taskCommandType = formCommand.getEventMsg().first;
126     std::shared_ptr<FormCommandQueue> formCommandQueue;
127     if (taskCommandType == TaskCommandType::RENDER_FORM || taskCommandType == TaskCommandType::RECYCLE_FORM) {
128         formCommandQueue = GetOrCreateFormStatusQueue(formId, remoteObjectOfHost, FormStatus::RECOVERED);
129     } else if (taskCommandType == TaskCommandType::RECOVER_FORM) {
130         formCommandQueue = GetOrCreateFormStatusQueue(formId, remoteObjectOfHost, FormStatus::RECYCLED);
131     } else {
132         HILOG_ERROR("taskCommandType is unknown , formId:%{public}" PRId64 ". ", formId);
133         return;
134     }
135     if (formCommandQueue == nullptr) {
136         HILOG_ERROR("formCommandQueue is null , formId:%{public}" PRId64 ". ", formId);
137         return;
138     }
139 
140     formCommandQueue->PushFormCommand(formCommand);
141     PostFormCommandTask(formCommandQueue, formId);
142 }
143 
PostFormDeleteTask(FormCommand formCommand,const std::string compId)144 void FormStatusQueue::PostFormDeleteTask(FormCommand formCommand, const std::string compId)
145 {
146     auto formId = formCommand.getFormId();
147     auto ms = formCommand.getMs();
148     auto func = formCommand.getFunc();
149     HILOG_INFO("PostFormDeleteTask , formId:%{public}" PRId64 ". ", formId);
150     DeleteFormStatusQueueIfNecessary(formId, compId);
151     ScheduleTask(ms, func);
152 }
153 
PostFormCommandTask(std::shared_ptr<FormCommandQueue> formCommandQueue,const int64_t formId)154 void FormStatusQueue::PostFormCommandTask(std::shared_ptr<FormCommandQueue> formCommandQueue, const int64_t formId)
155 {
156     if (FormStatusMgr::GetInstance().isProcessableFormStatus(formId)) {
157         FormCommand formCommand{};
158         if (!formCommandQueue->PopFormCommand(formCommand)) {
159             HILOG_INFO("formCommandQueue is empty, formId:%{public}" PRId64 ". ", formId);
160             return;
161         }
162         ProcessTask(formCommand);
163     } else {
164         HILOG_INFO("FormStatus is unProcessable, formId:%{public}" PRId64 ". ", formId);
165     }
166 }
167 
PostFormCommandTaskByFormId(const int64_t formId)168 void FormStatusQueue::PostFormCommandTaskByFormId(const int64_t formId)
169 {
170     if (FormStatusMgr::GetInstance().isProcessableFormStatus(formId)) {
171         std::shared_ptr<FormCommandQueue> formCommandQueue;
172         {
173             std::shared_lock<std::shared_mutex> lock(formCommandQueueMapMutex_);
174             if (formCommandQueueMap_.find(formId) == formCommandQueueMap_.end()) {
175                 HILOG_ERROR("formCommandQueueMap_ query failed, formId:%{public}" PRId64 ". ", formId);
176                 return;
177             }
178             formCommandQueue = formCommandQueueMap_[formId];
179         }
180 
181         FormCommand formCommand{};
182         if (!formCommandQueue->PopFormCommand(formCommand)) {
183             HILOG_INFO("formCommandQueue is empty, formId:%{public}" PRId64 ". ", formId);
184             return;
185         }
186         ProcessTask(formCommand);
187     } else {
188         HILOG_INFO("FormStatus is unProcessable, formId:%{public}" PRId64 ". ", formId);
189     }
190 }
191 
ProcessTask(FormCommand & formCommand)192 void FormStatusQueue::ProcessTask(FormCommand &formCommand)
193 {
194     auto taskCommandType = formCommand.getEventMsg().first;
195     auto formId = formCommand.getFormId();
196     auto ms = formCommand.getMs();
197     auto func = formCommand.getFunc();
198 
199     if (taskCommandType == TaskCommandType::RENDER_FORM) {
200         FormStatusMgr::GetInstance().SetFormStatus(formId, FormStatus::UNPROCESSABLE);
201         ScheduleTask(ms, func);
202     } else if (taskCommandType == TaskCommandType::RECOVER_FORM) {
203         FormStatusMgr::GetInstance().SetFormStatus(formId, FormStatus::RECOVERING);
204         ScheduleTask(ms, func);
205     } else if (taskCommandType == TaskCommandType::RECYCLE_FORM) {
206         FormStatusMgr::GetInstance().SetFormStatus(formId, FormStatus::RECYCLING);
207         ScheduleTask(ms, func);
208     } else {
209         HILOG_ERROR("ProcessTask Error!, formId :%{public}" PRId64 ". ", formId);
210     }
211 }
212 
PostTimeOutReAddForm(const int64_t formId)213 void FormStatusQueue::PostTimeOutReAddForm(const int64_t formId)
214 {
215     HILOG_DEBUG("start");
216     if (formHostTokenMap_.find(formId) == formHostTokenMap_.end() || formHostTokenMap_[formId] == nullptr) {
217         HILOG_ERROR("formHostToken is null, formId:%{public}" PRId64 ". ", formId);
218         return;
219     }
220     auto remoteObjectOfHost = formHostTokenMap_[formId];
221     auto timeOutReAddForm = [formId, remoteObjectOfHost]() {
222         FormStatusQueue::GetInstance().TimeOutReAddForm(formId, remoteObjectOfHost);
223     };
224     ScheduleDelayTask(
225         std::make_pair((int64_t)TaskCommandType::READDFORM_FORM, formId),
226         FORM_MAX_TIME_OUT,
227         timeOutReAddForm);
228     HILOG_DEBUG("end");
229 }
230 
TimeOutReAddForm(const int64_t & formId,const sptr<IRemoteObject> & remoteObjectOfHost)231 void FormStatusQueue::TimeOutReAddForm(const int64_t &formId, const sptr<IRemoteObject> &remoteObjectOfHost)
232 {
233     HILOG_INFO("start");
234     sptr<IFormHost> remoteFormHost = iface_cast<IFormHost>(remoteObjectOfHost);
235     if (remoteFormHost == nullptr) {
236         HILOG_ERROR("get formHostProxy failed");
237         return;
238     }
239     remoteFormHost->OnError(ERR_APPEXECFWK_FORM_STATUS_TIMIE_OUT, "form status timeout, try reAddForm.");
240     HILOG_INFO("end");
241 }
242 
CancelTimeOutReAddForm(const int64_t & formId)243 void FormStatusQueue::CancelTimeOutReAddForm(const int64_t &formId)
244 {
245     CancelDelayTask(std::make_pair((int64_t)TaskCommandType::READDFORM_FORM, formId));
246 }
247 }  // namespace AppExecFwk
248 }  // namespace OHOS
249