1 /*
2 * Copyright (c) 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 "form_render_service_mgr.h"
17
18 #include <cstddef>
19 #include <memory>
20
21 #include "event_handler.h"
22 #include "fms_log_wrapper.h"
23 #include "form_constants.h"
24 #include "form_render_event_report.h"
25 #include "form_render_service_extension.h"
26 #include "js_runtime.h"
27 #include "service_extension.h"
28 #include "form_memmgr_client.h"
29 #ifdef SUPPORT_POWER
30 #include "power_mgr_client.h"
31 #endif
32 #include "status_mgr_center/form_render_status_task_mgr.h"
33 #include "status_mgr_center/form_render_status_mgr.h"
34
35 namespace OHOS {
36 namespace AppExecFwk {
37 namespace FormRender {
38 namespace {
39 constexpr int32_t RENDER_FORM_FAILED = -1;
40 constexpr int32_t RELOAD_FORM_FAILED = -1;
41 constexpr int32_t RECYCLE_FORM_FAILED = -1;
42 constexpr int32_t SET_VISIBLE_CHANGE_FAILED = -1;
43 constexpr int32_t FORM_RENDER_TASK_DELAY_TIME = 20; // ms
44 constexpr int32_t ENABLE_FORM_FAILED = -1;
45 constexpr int32_t UPDATE_FORM_SIZE_FAILED = -1;
46 constexpr int32_t FORM_CLIENT_INVALID = -1;
47 constexpr int64_t MIN_DURATION_MS = 1500;
48 constexpr int64_t TASK_ONCONFIGURATIONUPDATED_DELAY_MS = 1000;
49 const std::string TASK_ONCONFIGURATIONUPDATED = "FormRenderServiceMgr::OnConfigurationUpdated";
50 const std::string FORM_RENDER_SERIAL_QUEUE = "FormRenderSerialQueue";
51 } // namespace
52 using namespace AbilityRuntime;
53 using namespace OHOS::AAFwk::GlobalConfigurationKey;
54
55 const static std::unordered_set<std::string> configItemList_ = {
56 SYSTEM_COLORMODE, SYSTEM_LANGUAGE, SYSTEM_FONT_SIZE_SCALE, SYSTEM_FONT_WEIGHT_SCALE
57 };
58
FormRenderServiceMgr()59 FormRenderServiceMgr::FormRenderServiceMgr()
60 {
61 serialQueue_ = std::make_unique<FormRenderSerialQueue>(FORM_RENDER_SERIAL_QUEUE);
62 FormRenderStatusTaskMgr::GetInstance().SetSerialQueue(serialQueue_);
63 appliedConfig_ = std::make_shared<AppExecFwk::Configuration>();
64 }
65
66 FormRenderServiceMgr::~FormRenderServiceMgr() = default;
67
RenderForm(const FormJsInfo & formJsInfo,const Want & want,const sptr<IRemoteObject> & callerToken)68 int32_t FormRenderServiceMgr::RenderForm(
69 const FormJsInfo &formJsInfo, const Want &want, const sptr<IRemoteObject> &callerToken)
70 {
71 HILOG_INFO("Render form,bundleName=%{public}s,abilityName=%{public}s,formName=%{public}s,"
72 "moduleName=%{public}s,jsFormCodePath=%{public}s,formSrc=%{public}s,formId=%{public}" PRId64,
73 formJsInfo.bundleName.c_str(),
74 formJsInfo.abilityName.c_str(),
75 formJsInfo.formName.c_str(),
76 formJsInfo.moduleName.c_str(),
77 formJsInfo.jsFormCodePath.c_str(),
78 formJsInfo.formSrc.c_str(),
79 formJsInfo.formId);
80
81 SetCriticalTrueOnFormActivity();
82 sptr<IFormSupply> formSupplyClient = iface_cast<IFormSupply>(callerToken);
83 if (formSupplyClient == nullptr) {
84 HILOG_ERROR("null IFormSupply");
85 return ERR_APPEXECFWK_FORM_BIND_PROVIDER_FAILED;
86 }
87 SetFormSupplyClient(formSupplyClient);
88 HILOG_DEBUG("connectId:%{public}d", want.GetIntParam(Constants::FORM_CONNECT_ID, 0L));
89
90 std::string eventId = want.GetStringParam(Constants::FORM_STATUS_EVENT_ID);
91 if (eventId.empty()) {
92 HILOG_ERROR("GetTid failed");
93 return ERR_APPEXECFWK_FORM_BIND_PROVIDER_FAILED;
94 }
95 HILOG_INFO("eventId:%{public}s", eventId.c_str());
96 FormRenderStatusMgr::GetInstance().SetFormEventId(formJsInfo.formId, eventId);
97
98 std::string uid = want.GetStringParam(Constants::FORM_SUPPLY_UID);
99 if (uid.empty()) {
100 HILOG_ERROR("GetUid failed");
101 return ERR_APPEXECFWK_FORM_BIND_PROVIDER_FAILED;
102 }
103 Want formRenderWant(want);
104 const auto result = UpdateRenderRecordByUid(uid, formRenderWant, formJsInfo, formSupplyClient);
105 if (result != ERR_OK) {
106 HILOG_ERROR("render form failed");
107 FormRenderStatusTaskMgr::GetInstance().OnRenderFormDone(
108 formJsInfo.formId, FormFsmEvent::RENDER_FORM_FAIL, formSupplyClient);
109 }
110 formSupplyClient->OnRenderTaskDone(formJsInfo.formId, formRenderWant);
111 return result;
112 }
113
StopRenderingForm(const FormJsInfo & formJsInfo,const Want & want,const sptr<IRemoteObject> & callerToken)114 int32_t FormRenderServiceMgr::StopRenderingForm(
115 const FormJsInfo &formJsInfo, const Want &want, const sptr<IRemoteObject> &callerToken)
116 {
117 HILOG_INFO("call, formId:%{public}" PRId64, formJsInfo.formId);
118 SetCriticalTrueOnFormActivity();
119 sptr<IFormSupply> formSupplyClient = iface_cast<IFormSupply>(callerToken);
120 if (formSupplyClient == nullptr) {
121 HILOG_ERROR("null IFormSupply");
122 return ERR_APPEXECFWK_FORM_BIND_PROVIDER_FAILED;
123 }
124 std::string uid = want.GetStringParam(Constants::FORM_SUPPLY_UID);
125 std::string eventId = want.GetStringParam(Constants::FORM_STATUS_EVENT_ID);
126 if (uid.empty() || eventId.empty()) {
127 HILOG_ERROR("GetUid or GetEventid failed");
128 return ERR_APPEXECFWK_FORM_BIND_PROVIDER_FAILED;
129 }
130 FormRenderStatusMgr::GetInstance().SetFormEventId(formJsInfo.formId, eventId);
131
132 bool isRenderGroupEmpty = false;
133 sptr<IRemoteObject> hostToken = want.GetRemoteObject(Constants::PARAM_FORM_HOST_TOKEN);
134 {
135 std::shared_ptr<FormRenderRecord> search = nullptr;
136 GetRenderRecordById(search, uid);
137 if (search == nullptr) {
138 HILOG_ERROR("get render record fail");
139 return RENDER_FORM_FAILED;
140 }
141
142 std::string compId = want.GetStringParam(Constants::FORM_RENDER_COMP_ID);
143 search->DeleteRenderRecord(formJsInfo.formId, compId, hostToken, isRenderGroupEmpty);
144 const auto result = DeleteRenderRecordByUid(uid, search);
145 if (result != ERR_OK) {
146 return result;
147 }
148 }
149
150 HILOG_INFO("connectId:%{public}d", want.GetIntParam(Constants::FORM_CONNECT_ID, 0L));
151 if (isRenderGroupEmpty) {
152 formSupplyClient->OnStopRenderingTaskDone(formJsInfo.formId, want);
153 FormRenderStatusTaskMgr::GetInstance().OnDeleteFormDone(
154 formJsInfo.formId, FormFsmEvent::DELETE_FORM_FINISH, formSupplyClient);
155 } else {
156 FormRenderStatusTaskMgr::GetInstance().OnDeleteFormDone(
157 formJsInfo.formId, FormFsmEvent::DELETE_FORM_DONE, formSupplyClient);
158 }
159
160 std::lock_guard<std::mutex> lock(renderRecordMutex_);
161 SetCriticalFalseOnAllFormInvisible();
162
163 return ERR_OK;
164 }
165
ReleaseRenderer(int64_t formId,const std::string & compId,const std::string & uid,const Want & want)166 int32_t FormRenderServiceMgr::ReleaseRenderer(
167 int64_t formId, const std::string &compId, const std::string &uid, const Want &want)
168 {
169 HILOG_INFO("formId:%{public}" PRId64 ",compId:%{public}s,uid:%{public}s", formId, compId.c_str(), uid.c_str());
170 SetCriticalTrueOnFormActivity();
171 std::string eventId = want.GetStringParam(Constants::FORM_STATUS_EVENT_ID);
172 if (formId <= 0 || compId.empty() || uid.empty() || eventId.empty()) {
173 HILOG_ERROR("param invalid");
174 return ERR_APPEXECFWK_FORM_BIND_PROVIDER_FAILED;
175 }
176 FormRenderStatusMgr::GetInstance().SetFormEventId(formId, eventId);
177
178 sptr<IFormSupply> formSupplyClient = GetFormSupplyClient();
179 if (formSupplyClient == nullptr) {
180 HILOG_ERROR("null formSupplyClient");
181 return FORM_CLIENT_INVALID;
182 }
183
184 std::lock_guard<std::mutex> lock(renderRecordMutex_);
185 bool isRenderGroupEmpty = false;
186 auto search = renderRecordMap_.find(uid);
187 if (search == renderRecordMap_.end()) {
188 HILOG_ERROR("invalid record,formId:%{public}" PRId64, formId);
189 return RENDER_FORM_FAILED;
190 }
191
192 if (!search->second) {
193 HILOG_ERROR("record invalid,formId:%{public}" PRId64, formId);
194 return RENDER_FORM_FAILED;
195 }
196
197 search->second->ReleaseRenderer(formId, compId, isRenderGroupEmpty);
198 HILOG_INFO("end,isRenderGroupEmpty:%{public}d", isRenderGroupEmpty);
199 FormRenderStatusTaskMgr::GetInstance().OnRecycleFormDone(formId, FormFsmEvent::RECYCLE_FORM_DONE, formSupplyClient);
200 FormRenderStatusTaskMgr::GetInstance().CancelRecycleTimeout(formId);
201 if (isRenderGroupEmpty) {
202 search->second->Release();
203 }
204
205 FormRenderEventReport::StopReleaseTimeoutReportTimer(formId);
206
207 SetCriticalFalseOnAllFormInvisible();
208
209 return ERR_OK;
210 }
211
CleanFormHost(const sptr<IRemoteObject> & hostToken)212 int32_t FormRenderServiceMgr::CleanFormHost(const sptr<IRemoteObject> &hostToken)
213 {
214 HILOG_INFO("Form host is died,clean renderRecord");
215 SetCriticalTrueOnFormActivity();
216 std::lock_guard<std::mutex> lock(renderRecordMutex_);
217 for (auto iter = renderRecordMap_.begin(); iter != renderRecordMap_.end();) {
218 auto renderRecord = iter->second;
219 if (renderRecord && renderRecord->HandleHostDied(hostToken)) {
220 HILOG_DEBUG("empty renderRecord,remove");
221 iter = renderRecordMap_.erase(iter);
222 } else {
223 ++iter;
224 }
225 }
226
227 SetCriticalFalseOnAllFormInvisible();
228
229 return ERR_OK;
230 }
231
ReloadForm(const std::vector<FormJsInfo> && formJsInfos,const Want & want)232 int32_t FormRenderServiceMgr::ReloadForm(const std::vector<FormJsInfo> &&formJsInfos, const Want &want)
233 {
234 HILOG_INFO("ReloadForm start");
235
236 std::string bundleName = want.GetStringParam(Constants::PARAM_BUNDLE_NAME_KEY);
237 if (bundleName.empty()) {
238 HILOG_ERROR("GetBundleName failed");
239 return ERR_APPEXECFWK_FORM_BIND_PROVIDER_FAILED;
240 }
241
242 int32_t ret = ReloadFormRecord(std::forward<decltype(formJsInfos)>(formJsInfos), want);
243 if (ret != ERR_OK) {
244 HILOG_ERROR("Reload form record failed, ret = %{public}d", ret);
245 FormRenderEventReport::SendFormFailedEvent(FormEventName::RELOAD_FORM_FAILED,
246 0,
247 bundleName,
248 "",
249 static_cast<int32_t>(ReloadFormErrorType::RELOAD_FORM_RELOAD_FORM_ERROR),
250 ret);
251 }
252
253 return ret;
254 }
255
ReloadFormRecord(const std::vector<FormJsInfo> && formJsInfos,const Want & want)256 int32_t FormRenderServiceMgr::ReloadFormRecord(const std::vector<FormJsInfo> &&formJsInfos, const Want &want)
257 {
258 SetCriticalTrueOnFormActivity();
259 std::string uid = want.GetStringParam(Constants::FORM_SUPPLY_UID);
260 if (uid.empty()) {
261 HILOG_ERROR("Get uid failed");
262 return ERR_APPEXECFWK_FORM_BIND_PROVIDER_FAILED;
263 }
264 std::shared_ptr<FormRenderRecord> search = nullptr;
265 GetRenderRecordById(search, uid);
266 if (search != nullptr) {
267 return search->ReloadFormRecord(std::forward<decltype(formJsInfos)>(formJsInfos), want);
268 }
269
270 HILOG_ERROR("Not exist renderRecord");
271 return ERR_APPEXECFWK_FORM_NOT_EXIST_RENDER_RECORD;
272 }
273
OnUnlock()274 int32_t FormRenderServiceMgr::OnUnlock()
275 {
276 HILOG_INFO("OnUnlock start");
277 SetCriticalTrueOnFormActivity();
278 std::lock_guard<std::mutex> lock(renderRecordMutex_);
279 if (isVerified_) {
280 HILOG_WARN("Has been unlocked in render form, maybe miss or delay unlock event");
281 return ERR_OK;
282 }
283
284 isVerified_ = true;
285 for (const auto &iter : renderRecordMap_) {
286 if (iter.second) {
287 iter.second->OnUnlock();
288 }
289 }
290
291 SetCriticalFalseOnAllFormInvisible();
292
293 return ERR_OK;
294 }
295
SetVisibleChange(const int64_t formId,bool isVisible,const Want & want)296 int32_t FormRenderServiceMgr::SetVisibleChange(const int64_t formId, bool isVisible, const Want &want)
297 {
298 HILOG_INFO("formId:%{public}" PRId64 " isVisble: %{public}d", formId, isVisible);
299 if (formId <= 0) {
300 HILOG_ERROR("formId is negative");
301 return ERR_APPEXECFWK_FORM_INVALID_FORM_ID;
302 }
303
304 std::string uid = want.GetStringParam(Constants::FORM_SUPPLY_UID);
305 if (uid.empty()) {
306 HILOG_ERROR("empty uid,formId:%{public}" PRId64, formId);
307 return ERR_APPEXECFWK_FORM_BIND_PROVIDER_FAILED;
308 }
309 HILOG_INFO("formId:%{public}" PRId64 ",uid:%{public}s", formId, uid.c_str());
310
311 if (isVisible) {
312 SetCriticalTrueOnFormActivity();
313 }
314 std::lock_guard<std::mutex> lock(renderRecordMutex_);
315 if (auto search = renderRecordMap_.find(uid); search != renderRecordMap_.end()) {
316 if (search->second == nullptr) {
317 HILOG_ERROR("null renderRecord of %{public}" PRId64, formId);
318 return SET_VISIBLE_CHANGE_FAILED;
319 }
320 auto ret = search->second->SetVisibleChange(formId, isVisible);
321 if (!isVisible) {
322 SetCriticalFalseOnAllFormInvisible();
323 }
324 if (ret != ERR_OK) {
325 HILOG_ERROR("SetVisibleChange %{public}" PRId64 " failed.", formId);
326 return ret;
327 }
328 } else {
329 HILOG_ERROR("can't find render record of %{public}" PRId64, formId);
330 return SET_VISIBLE_CHANGE_FAILED;
331 }
332 return ERR_OK;
333 }
334
OnConfigurationUpdated(const std::shared_ptr<OHOS::AppExecFwk::Configuration> & configuration)335 void FormRenderServiceMgr::OnConfigurationUpdated(const std::shared_ptr<OHOS::AppExecFwk::Configuration> &configuration)
336 {
337 HILOG_DEBUG("OnConfigurationUpdated start");
338 if (!configuration) {
339 HILOG_ERROR("null configuration");
340 return;
341 }
342
343 SetCriticalTrueOnFormActivity();
344
345 SetConfiguration(configuration);
346
347 #ifdef SUPPORT_POWER
348 bool screenOnFlag = PowerMgr::PowerMgrClient::GetInstance().IsScreenOn();
349 bool collaborationScreenOnFlag = PowerMgr::PowerMgrClient::GetInstance().IsCollaborationScreenOn();
350 if (!screenOnFlag && !collaborationScreenOnFlag) {
351 HILOG_WARN("screen off");
352 hasCachedConfig_ = true;
353 return;
354 }
355 #endif
356
357 serialQueue_->CancelDelayTask(TASK_ONCONFIGURATIONUPDATED);
358 auto duration = std::chrono::steady_clock::now() - configUpdateTime_;
359 if (std::chrono::duration_cast<std::chrono::milliseconds>(duration).count() < MIN_DURATION_MS) {
360 HILOG_INFO("OnConfigurationUpdated ignored");
361 auto configUpdateFunc = [this]() {
362 HILOG_INFO("OnConfigurationUpdated task run");
363 this->OnConfigurationUpdatedInner();
364 };
365 serialQueue_->ScheduleDelayTask(TASK_ONCONFIGURATIONUPDATED,
366 TASK_ONCONFIGURATIONUPDATED_DELAY_MS, configUpdateFunc);
367 return;
368 }
369 OnConfigurationUpdatedInner();
370
371 std::lock_guard<std::mutex> lock(renderRecordMutex_);
372 SetCriticalFalseOnAllFormInvisible();
373 }
374
OnConfigurationUpdatedInner()375 void FormRenderServiceMgr::OnConfigurationUpdatedInner()
376 {
377 sptr<IFormSupply> formSupplyClient = GetFormSupplyClient();
378 if (formSupplyClient == nullptr) {
379 HILOG_ERROR("null formSupplyClient");
380 return;
381 }
382
383 // Retrieve configuration items that have not yet been issued for execution
384 std::shared_ptr<OHOS::AppExecFwk::Configuration> applyConfig = GetNeedApplyConfig();
385 // Update all configuration item caches
386 CacheAppliedConfig();
387 configUpdateTime_ = std::chrono::steady_clock::now();
388 size_t allFormCount = 0;
389 {
390 std::lock_guard<std::mutex> lock(renderRecordMutex_);
391 for (auto iter = renderRecordMap_.begin(); iter != renderRecordMap_.end(); ++iter) {
392 if (iter->second) {
393 iter->second->UpdateConfiguration(applyConfig, formSupplyClient);
394 allFormCount += iter->second->FormCount();
395 }
396 }
397 }
398 HILOG_INFO("OnConfigurationUpdated %{public}zu forms updated.", allFormCount);
399 hasCachedConfig_ = false;
400 PerformanceEventInfo eventInfo;
401 eventInfo.timeStamp = FormRenderEventReport::GetNowMillisecond();
402 eventInfo.bundleName = Constants::FRS_BUNDLE_NAME;
403 eventInfo.sceneId = Constants::CPU_SCENE_ID_CONFIG_UPDATE;
404 FormRenderEventReport::SendPerformanceEvent(SceneType::CPU_SCENE_ENTRY, eventInfo);
405 }
406
SetConfiguration(const std::shared_ptr<OHOS::AppExecFwk::Configuration> & config)407 void FormRenderServiceMgr::SetConfiguration(const std::shared_ptr<OHOS::AppExecFwk::Configuration> &config)
408 {
409 std::lock_guard<std::mutex> lock(configMutex_);
410 if (config != nullptr && configuration_ != nullptr) {
411 for (const auto &item : configItemList_) {
412 std::string newValue = config->GetItem(item);
413 std::string oldValue = configuration_->GetItem(item);
414 if (newValue.empty() && !oldValue.empty()) {
415 config->AddItem(item, oldValue);
416 }
417 }
418
419 configuration_ = config;
420 HILOG_INFO("current configuration_:%{public}s", configuration_->GetName().c_str());
421 return;
422 }
423
424 configuration_ = config;
425 }
426
RunCachedConfigurationUpdated()427 void FormRenderServiceMgr::RunCachedConfigurationUpdated()
428 {
429 HILOG_INFO("RunCachedConfigUpdated");
430 if (hasCachedConfig_) {
431 SetCriticalTrueOnFormActivity();
432 OnConfigurationUpdatedInner();
433
434 std::lock_guard<std::mutex> lock(renderRecordMutex_);
435 SetCriticalFalseOnAllFormInvisible();
436 }
437 }
438
FormRenderGCTask(const std::string & uid)439 void FormRenderServiceMgr::FormRenderGCTask(const std::string &uid)
440 {
441 auto mainHandler = std::make_shared<AppExecFwk::EventHandler>(AppExecFwk::EventRunner::GetMainEventRunner());
442 if (mainHandler == nullptr) {
443 HILOG_ERROR("null mainHandler");
444 return;
445 }
446 auto formRenderGCFunc = [uid]() { FormRenderServiceMgr::GetInstance().FormRenderGC(uid); };
447 mainHandler->PostTask(formRenderGCFunc, "FormRenderGC", FORM_RENDER_TASK_DELAY_TIME);
448 }
449
FormRenderGC(const std::string & uid)450 void FormRenderServiceMgr::FormRenderGC(const std::string &uid)
451 {
452 HILOG_INFO("form gc, uid is %{public}s", uid.c_str());
453 std::lock_guard<std::mutex> lock(renderRecordMutex_);
454 if (auto search = renderRecordMap_.find(uid); search != renderRecordMap_.end()) {
455 search->second->FormRenderGC();
456 }
457 }
458
RecycleForm(const int64_t formId,const Want & want)459 int32_t FormRenderServiceMgr::RecycleForm(const int64_t formId, const Want &want)
460 {
461 if (formId <= 0) {
462 HILOG_ERROR("formId is negative");
463 return ERR_APPEXECFWK_FORM_INVALID_FORM_ID;
464 }
465 SetCriticalTrueOnFormActivity();
466
467 std::string uid = want.GetStringParam(Constants::FORM_SUPPLY_UID);
468 std::string eventId = want.GetStringParam(Constants::FORM_STATUS_EVENT_ID);
469 if (uid.empty() || eventId.empty()) {
470 HILOG_ERROR("empty uid or eventId, formId:%{public}" PRId64, formId);
471 return ERR_APPEXECFWK_FORM_BIND_PROVIDER_FAILED;
472 }
473 HILOG_INFO("formId:%{public}" PRId64 ",uid:%{public}s", formId, uid.c_str());
474 FormRenderStatusMgr::GetInstance().SetFormEventId(formId, eventId);
475
476 std::string statusData;
477 const auto result = RecycleFormByUid(uid, statusData, formId);
478 if (result != ERR_OK) {
479 HILOG_ERROR("RecycleFormByUid failed");
480 return result;
481 }
482
483 sptr<IFormSupply> formSupplyClient = GetFormSupplyClient();
484 if (formSupplyClient == nullptr) {
485 HILOG_ERROR("null formSupplyClient, formId:%{public}" PRId64, formId);
486 return RECYCLE_FORM_FAILED;
487 }
488 FormRenderStatusTaskMgr::GetInstance().OnRecycleForm(
489 formId, FormFsmEvent::RECYCLE_DATA_DONE, statusData, want, formSupplyClient);
490 FormRenderStatusTaskMgr::GetInstance().ScheduleRecycleTimeout(formId);
491
492 FormRenderEventReport::StartReleaseTimeoutReportTimer(formId, uid);
493
494 std::lock_guard<std::mutex> lock(renderRecordMutex_);
495 SetCriticalFalseOnAllFormInvisible();
496
497 return ERR_OK;
498 }
499
RecoverForm(const FormJsInfo & formJsInfo,const Want & want)500 int32_t FormRenderServiceMgr::RecoverForm(const FormJsInfo &formJsInfo, const Want &want)
501 {
502 auto formId = formJsInfo.formId;
503 if (formId <= 0) {
504 HILOG_ERROR("formId is negative");
505 return ERR_APPEXECFWK_FORM_INVALID_FORM_ID;
506 }
507
508 SetCriticalTrueOnFormActivity();
509
510 std::string uid = want.GetStringParam(Constants::FORM_SUPPLY_UID);
511 std::string eventId = want.GetStringParam(Constants::FORM_STATUS_EVENT_ID);
512 if (uid.empty() || eventId.empty()) {
513 HILOG_ERROR("empty uid or eventId, formId:%{public}" PRId64, formId);
514 return ERR_APPEXECFWK_FORM_BIND_PROVIDER_FAILED;
515 }
516 FormRenderStatusMgr::GetInstance().SetFormEventId(formJsInfo.formId, eventId);
517 HILOG_INFO("formId:%{public}" PRId64 ", connectId:%{public}d, uid:%{public}s",
518 formId,
519 want.GetIntParam(Constants::FORM_CONNECT_ID, 0L),
520 uid.c_str());
521
522 std::string statusData = want.GetStringParam(Constants::FORM_STATUS_DATA);
523 if (statusData.empty()) {
524 HILOG_WARN("empty statusData of %{public}s", std::to_string(formId).c_str());
525 }
526 return RecoverFormByUid(formJsInfo, want, uid, statusData);
527 }
528
ConfirmUnlockState(Want & renderWant)529 void FormRenderServiceMgr::ConfirmUnlockState(Want &renderWant)
530 {
531 // Ensure that there are no issues with adding form and unlocking drawing concurrency
532 if (isVerified_) {
533 renderWant.SetParam(Constants::FORM_RENDER_STATE, true);
534 } else if (renderWant.GetBoolParam(Constants::FORM_RENDER_STATE, false)) {
535 HILOG_WARN("Maybe unlock event is missed or delayed, all form record begin to render");
536 isVerified_ = true;
537 for (const auto &iter : renderRecordMap_) {
538 if (iter.second) {
539 iter.second->OnUnlock();
540 }
541 }
542 } else if (renderWant.GetBoolParam(Constants::FORM_RENDER_WITHOUT_UNLOCK_STATE, false)) {
543 HILOG_WARN("The current form allow render without unlocked");
544 renderWant.SetParam(Constants::FORM_RENDER_STATE, true);
545 }
546 }
547
UpdateFormSize(const int64_t formId,float width,float height,float borderWidth,const std::string & uid)548 int32_t FormRenderServiceMgr::UpdateFormSize(
549 const int64_t formId, float width, float height, float borderWidth, const std::string &uid)
550 {
551 SetCriticalTrueOnFormActivity();
552
553 std::lock_guard<std::mutex> lock(renderRecordMutex_);
554 if (auto search = renderRecordMap_.find(uid); search != renderRecordMap_.end()) {
555 if (search->second == nullptr) {
556 HILOG_ERROR("UpdateFormSize null renderRecord of %{public}" PRId64, formId);
557 return UPDATE_FORM_SIZE_FAILED;
558 }
559 search->second->UpdateFormSizeOfGroups(formId, width, height, borderWidth);
560 return ERR_OK;
561 }
562 HILOG_ERROR("can't find render record of %{public}" PRId64, formId);
563 return UPDATE_FORM_SIZE_FAILED;
564 }
565
SetFormSupplyClient(const sptr<IFormSupply> & formSupplyClient)566 void FormRenderServiceMgr::SetFormSupplyClient(const sptr<IFormSupply> &formSupplyClient)
567 {
568 std::lock_guard<std::mutex> lock(formSupplyMutex_);
569 formSupplyClient_ = formSupplyClient;
570 }
571
GetFormSupplyClient()572 sptr<IFormSupply> FormRenderServiceMgr::GetFormSupplyClient()
573 {
574 std::lock_guard<std::mutex> lock(formSupplyMutex_);
575 return formSupplyClient_;
576 }
577
IsRenderRecordExist(const std::string & uid)578 bool FormRenderServiceMgr::IsRenderRecordExist(const std::string &uid)
579 {
580 std::lock_guard<std::mutex> lock(renderRecordMutex_);
581 auto iterator = renderRecordMap_.find(uid);
582 return iterator != renderRecordMap_.end();
583 }
584
UpdateRenderRecordByUid(const std::string & uid,Want & formRenderWant,const FormJsInfo & formJsInfo,const sptr<IFormSupply> & formSupplyClient)585 int32_t FormRenderServiceMgr::UpdateRenderRecordByUid(const std::string &uid, Want &formRenderWant,
586 const FormJsInfo &formJsInfo, const sptr<IFormSupply> &formSupplyClient)
587 {
588 if (formSupplyClient == nullptr) {
589 HILOG_ERROR("null IFormSupply");
590 return ERR_APPEXECFWK_FORM_BIND_PROVIDER_FAILED;
591 }
592 int32_t result = ERR_OK;
593 sptr<IRemoteObject> hostToken = formRenderWant.GetRemoteObject(Constants::PARAM_FORM_HOST_TOKEN);
594 std::lock_guard<std::mutex> lock(renderRecordMutex_);
595 ConfirmUnlockState(formRenderWant);
596 auto search = renderRecordMap_.find(uid);
597 if (search != renderRecordMap_.end()) {
598 result = search->second->UpdateRenderRecord(formJsInfo, formRenderWant, hostToken);
599 } else {
600 auto record = FormRenderRecord::Create(formJsInfo.bundleName, uid, formJsInfo.isDynamic, formSupplyClient);
601 if (record == nullptr) {
602 HILOG_ERROR("null record");
603 return RENDER_FORM_FAILED;
604 }
605 record->SetConfiguration(configuration_);
606 result = record->UpdateRenderRecord(formJsInfo, formRenderWant, hostToken);
607 if (renderRecordMap_.empty()) {
608 FormMemmgrClient::GetInstance().SetCritical(true);
609 }
610 renderRecordMap_.emplace(uid, record);
611 FormRenderGCTask(uid);
612 }
613 return result;
614 }
615
GetRenderRecordById(std::shared_ptr<FormRenderRecord> & search,const std::string & uid)616 void FormRenderServiceMgr::GetRenderRecordById(std::shared_ptr<FormRenderRecord> &search, const std::string &uid)
617 {
618 std::lock_guard<std::mutex> lock(renderRecordMutex_);
619 auto iterator = renderRecordMap_.find(uid);
620 if (iterator == renderRecordMap_.end() || !(iterator->second)) {
621 HILOG_ERROR("fail");
622 return;
623 }
624 search = iterator->second;
625 }
626
RecoverFormByUid(const FormJsInfo & formJsInfo,const Want & want,const std::string & uid,const std::string & statusData)627 int32_t FormRenderServiceMgr::RecoverFormByUid(
628 const FormJsInfo &formJsInfo, const Want &want, const std::string &uid, const std::string &statusData)
629 {
630 bool isRecoverFormToHandleClickEvent =
631 want.GetBoolParam(Constants::FORM_IS_RECOVER_FORM_TO_HANDLE_CLICK_EVENT, false);
632 std::lock_guard<std::mutex> lock(renderRecordMutex_);
633 if (auto search = renderRecordMap_.find(uid); search != renderRecordMap_.end()) {
634 if (search->second == nullptr) {
635 HILOG_ERROR("null renderRecord of %{public}" PRId64, formJsInfo.formId);
636 return RECYCLE_FORM_FAILED;
637 }
638 return search->second->RecoverForm(formJsInfo, statusData, isRecoverFormToHandleClickEvent);
639 }
640 HILOG_ERROR("can't find render record of %{public}" PRId64, formJsInfo.formId);
641 return RENDER_FORM_FAILED;
642 }
643
RecycleFormByUid(const std::string & uid,std::string & statusData,const int64_t formId)644 int32_t FormRenderServiceMgr::RecycleFormByUid(const std::string &uid, std::string &statusData, const int64_t formId)
645 {
646 std::lock_guard<std::mutex> lock(renderRecordMutex_);
647 auto search = renderRecordMap_.find(uid);
648 if (search != renderRecordMap_.end()) {
649 if (search->second == nullptr) {
650 HILOG_ERROR("null renderRecord of %{public}" PRId64, formId);
651 return RECYCLE_FORM_FAILED;
652 }
653 auto ret = search->second->RecycleForm(formId, statusData);
654 if (ret != ERR_OK) {
655 HILOG_ERROR("recycleForm failed, %{public}" PRId64, formId);
656 return ret;
657 }
658 } else {
659 HILOG_ERROR("can't find render record of %{public}" PRId64, formId);
660 return RECYCLE_FORM_FAILED;
661 }
662 if (statusData.empty()) {
663 HILOG_WARN("empty statusData of %{public}" PRId64, formId);
664 }
665 return ERR_OK;
666 }
667
DeleteRenderRecordByUid(const std::string & uid,const std::shared_ptr<FormRenderRecord> & search)668 int32_t FormRenderServiceMgr::DeleteRenderRecordByUid(
669 const std::string &uid, const std::shared_ptr<FormRenderRecord> &search)
670 {
671 if (!search) {
672 HILOG_ERROR("get render record fail");
673 return RENDER_FORM_FAILED;
674 }
675 std::lock_guard<std::mutex> lock(renderRecordMutex_);
676 if (search->IsEmpty() && !search->HasRenderFormTask()) {
677 auto iterator = renderRecordMap_.find(uid);
678 if (iterator == renderRecordMap_.end()) {
679 HILOG_ERROR("fail.");
680 return RENDER_FORM_FAILED;
681 }
682 renderRecordMap_.erase(iterator);
683 HILOG_INFO("DeleteRenderRecord success,uid:%{public}s", uid.c_str());
684 }
685 return ERR_OK;
686 }
687
688 /**
689 * @note Requires caller to hold FormRenderServiceMgr's renderRecordMutex_
690 * The calling context needs to be locked, and locking is not allowed inside the function
691 */
SetCriticalFalseOnAllFormInvisible()692 void FormRenderServiceMgr::SetCriticalFalseOnAllFormInvisible()
693 {
694 if (!FormMemmgrClient::GetInstance().IsCritical()) {
695 return;
696 }
697 // No need to lock here, the context needs to have a lock renderRecordMutex_
698 for (const auto &iter : renderRecordMap_) {
699 if (iter.second && !iter.second->IsAllFormsInvisible()) {
700 HILOG_INFO("is not AllFormsInvisible, uid: %{public}s", iter.first.c_str());
701 return;
702 }
703 }
704 FormMemmgrClient::GetInstance().SetCritical(false);
705 }
706
SetCriticalTrueOnFormActivity()707 void FormRenderServiceMgr::SetCriticalTrueOnFormActivity()
708 {
709 if (FormMemmgrClient::GetInstance().IsCritical()) {
710 return;
711 }
712 FormMemmgrClient::GetInstance().SetCritical(true);
713 }
714
GetNeedApplyConfig()715 std::shared_ptr<OHOS::AppExecFwk::Configuration> FormRenderServiceMgr::GetNeedApplyConfig()
716 {
717 std::lock_guard<std::mutex> lock(configMutex_);
718 if (configuration_ == nullptr || appliedConfig_ == nullptr) {
719 HILOG_ERROR("configuration_ or appliedConfig_ is null");
720 return nullptr;
721 }
722
723 auto config = std::make_shared<OHOS::AppExecFwk::Configuration>(*configuration_);
724 for (const auto &item : configItemList_) {
725 std::string oldValue = appliedConfig_->GetItem(item);
726 std::string newValue = configuration_->GetItem(item);
727 if (newValue.empty() || newValue == oldValue) {
728 config->RemoveItem(item);
729 }
730 }
731 HILOG_INFO("need apply config:%{public}s", config->GetName().c_str());
732 return config;
733 }
734
CacheAppliedConfig()735 void FormRenderServiceMgr::CacheAppliedConfig()
736 {
737 std::lock_guard<std::mutex> lock(configMutex_);
738 if (configuration_ == nullptr || appliedConfig_ == nullptr) {
739 HILOG_ERROR("configuration_ or appliedConfig_ is null");
740 return;
741 }
742
743 for (const auto &item : configItemList_) {
744 std::string value = configuration_->GetItem(item);
745 if (!value.empty()) {
746 appliedConfig_->AddItem(item, value);
747 }
748 }
749 HILOG_INFO("already applied config:%{public}s", appliedConfig_->GetName().c_str());
750 }
751 } // namespace FormRender
752 } // namespace AppExecFwk
753 } // namespace OHOS
754