• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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