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