• 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 "form_render_record.h"
17 
18 #include <chrono>
19 #include <cstdio>
20 #include <iostream>
21 #include <securec.h>
22 #include <string>
23 #include <thread>
24 #include <unistd.h>
25 #include <utility>
26 #include <fstream>
27 #include <sstream>
28 
29 #include "status_mgr_center/form_render_status_task_mgr.h"
30 #include "ecmascript/napi/include/jsnapi.h"
31 #include "extractor.h"
32 #include "fms_log_wrapper.h"
33 #include "form_constants.h"
34 #include "form_memory_guard.h"
35 #include "form_module_checker.h"
36 #include "form_render_event_report.h"
37 #include "nlohmann/json.hpp"
38 #include "xcollie/watchdog.h"
39 #include "dfx_dump_catcher.h"
40 
41 using namespace OHOS::AAFwk::GlobalConfigurationKey;
42 
43 namespace OHOS {
44 namespace AppExecFwk {
45 namespace FormRender {
46 namespace {
47 constexpr int32_t RENDER_FORM_FAILED = -1;
48 constexpr int32_t RELOAD_FORM_FAILED = -1;
49 constexpr int32_t RECYCLE_FORM_FAILED = -1;
50 constexpr size_t THREAD_BLOCK_TIMEOUT = 10 * 1000;
51 constexpr int32_t MEMORY_MONITOR_INTERVAL = Constants::MS_PER_DAY * 3;
52 constexpr size_t RUNTIME_MEMORY_LIMIT = 16 * 1024 * 1024;
53 constexpr int32_t SET_VISIBLE_CHANGE_FAILED = -1;
54 constexpr int32_t CHECK_THREAD_TIME = 3;
55 constexpr size_t THREAD_NAME_LEN = 15;
56 constexpr char FORM_RENDERER_COMP_ID[] = "ohos.extra.param.key.form_comp_id";
57 constexpr char FORM_RENDERER_PROCESS_ON_ADD_SURFACE[] = "ohos.extra.param.key.process_on_add_surface";
58 constexpr char RENDERING_BLOCK_MONITOR_PREFIX[] = "RenderingBlockMonitorTask_";
59 constexpr char MEMORY_MONITOR_PREFIX[] = "MemoryMonitorTask_";
60 
GetThreadNameByBundle(const std::string & bundleName)61 inline std::string GetThreadNameByBundle(const std::string &bundleName)
62 {
63     if (bundleName.length() <= THREAD_NAME_LEN) {
64         return bundleName;
65     }
66     return bundleName.substr(bundleName.length() - THREAD_NAME_LEN);
67 }
68 
GetPss()69 uint64_t GetPss()
70 {
71     pid_t pid = getprocpid();
72     std::string filePath = "/proc/" + std::to_string(pid) + "/smaps_rollup";
73     std::ifstream file(filePath);
74     if (!file.is_open()) {
75         HILOG_ERROR("pid:%{public}d get pss failed", pid);
76         return 0;
77     }
78     std::string line;
79     int64_t pss = 0;
80     int64_t swapPss = 0;
81     while (std::getline(file, line)) {
82         std::istringstream iss(line);
83         std::string key;
84         int64_t value;
85         std::string unit;
86         if (iss >> key >> value >> unit) {
87             if (key == "Pss:") {
88                 pss = value;
89             } else if (key == "SwapPss:") {
90                 swapPss = value;
91             }
92         }
93     }
94     file.close();
95     return pss + swapPss;
96 }
97 }
98 
ThreadState(int32_t maxState)99 ThreadState::ThreadState(int32_t maxState) : maxState_(maxState) {}
100 
ResetState()101 void ThreadState::ResetState()
102 {
103     state_ = 0;
104 }
105 
NextState()106 void ThreadState::NextState()
107 {
108     state_++;
109 }
110 
GetCurrentState()111 int32_t ThreadState::GetCurrentState()
112 {
113     return state_;
114 }
115 
IsMaxState()116 bool ThreadState::IsMaxState()
117 {
118     return state_ >= maxState_;
119 }
120 
Dump(const std::string & message)121 void HandlerDumper::Dump(const std::string &message)
122 {
123     HILOG_INFO("Message=%{public}s", message.c_str());
124     dumpInfo_ += message;
125 }
126 
GetTag()127 std::string HandlerDumper::GetTag()
128 {
129     return "";
130 }
131 
GetDumpInfo()132 std::string HandlerDumper::GetDumpInfo()
133 {
134     return dumpInfo_;
135 }
136 
Create(const std::string & bundleName,const std::string & uid,bool needMonitored,sptr<IFormSupply> client)137 std::shared_ptr<FormRenderRecord> FormRenderRecord::Create(
138     const std::string &bundleName, const std::string &uid, bool needMonitored, sptr<IFormSupply> client)
139 {
140     HILOG_INFO("bundleName is %{public}s, uid is %{public}s", bundleName.c_str(), uid.c_str());
141     std::shared_ptr<FormRenderRecord> renderRecord = std::make_shared<FormRenderRecord>(bundleName, uid, client);
142     if (!renderRecord) {
143         HILOG_ERROR("Create FormRenderRecord failed");
144         return nullptr;
145     }
146 
147     if (!renderRecord->CreateEventHandler(bundleName, needMonitored)) {
148         HILOG_ERROR("CreateEventHandler failed");
149         return nullptr;
150     }
151     return renderRecord;
152 }
153 
FormRenderRecord(const std::string & bundleName,const std::string & uid,const sptr<IFormSupply> client)154 FormRenderRecord::FormRenderRecord(
155     const std::string &bundleName, const std::string &uid, const sptr<IFormSupply> client)
156     : bundleName_(bundleName), uid_(uid), formSupplyClient_(client)
157 {
158     HILOG_INFO("bundleName is %{public}s,uid is %{public}s", bundleName.c_str(), uid.c_str());
159     threadState_ = std::make_unique<ThreadState>(CHECK_THREAD_TIME);
160     formSupplyClient_ = client;
161 }
162 
~FormRenderRecord()163 FormRenderRecord::~FormRenderRecord()
164 {
165     HILOG_INFO("call");
166     std::shared_ptr<EventHandler> eventHandler = GetEventHandler();
167     if (eventHandler == nullptr) {
168         HILOG_WARN("null eventHandler");
169         return;
170     }
171 
172     // Some resources need to be deleted in a JS thread
173     auto syncTask = [renderRecord = this]() {
174         if (renderRecord == nullptr) {
175             HILOG_ERROR("null renderRecord");
176             return;
177         }
178         renderRecord->HandleDestroyInJsThread();
179     };
180     eventHandler->PostSyncTask(syncTask, "Destory FormRenderRecord");
181     Release();
182     RemoveWatchDogThreadMonitor();
183 }
184 
HandleHostDied(const sptr<IRemoteObject> hostRemoteObj)185 bool FormRenderRecord::HandleHostDied(const sptr<IRemoteObject> hostRemoteObj)
186 {
187     HILOG_INFO("Form host is died,clean resources");
188     std::lock_guard<std::mutex> lock(hostsMapMutex_);
189     for (auto iter = hostsMapForFormId_.begin(); iter != hostsMapForFormId_.end();) {
190         std::unordered_set<sptr<IRemoteObject>, RemoteObjHash> &hosts = iter->second;
191         hosts.erase(hostRemoteObj);
192         if (hosts.empty()) {
193             int64_t formId = iter->first;
194             iter = hostsMapForFormId_.erase(iter);
195             DeleteRendererGroup(formId);
196         } else {
197             ++iter;
198         }
199     }
200     return hostsMapForFormId_.empty();
201 }
202 
DeleteRendererGroup(int64_t formId)203 void FormRenderRecord::DeleteRendererGroup(int64_t formId)
204 {
205     std::shared_ptr<EventHandler> eventHandler = GetEventHandler();
206     if (eventHandler == nullptr) {
207         HILOG_ERROR("null eventHandler");
208         return;
209     }
210 
211     auto task = [weak = weak_from_this(), formId]() {
212         auto renderRecord = weak.lock();
213         if (renderRecord == nullptr) {
214             HILOG_ERROR("null renderRecord");
215             return;
216         }
217 
218         renderRecord->HandleDeleteRendererGroup(formId);
219     };
220 
221     eventHandler->PostSyncTask(task, "DeleteRendererGroup");
222 }
223 
HandleDeleteRendererGroup(int64_t formId)224 void FormRenderRecord::HandleDeleteRendererGroup(int64_t formId)
225 {
226     std::lock_guard<std::mutex> lock(formRendererGroupMutex_);
227     formRendererGroupMap_.erase(formId);
228     DeleteFormLocation(formId);
229 }
230 
CreateEventHandler(const std::string & bundleName,bool needMonitored)231 bool FormRenderRecord::CreateEventHandler(const std::string &bundleName, bool needMonitored)
232 {
233     HILOG_INFO("call");
234     std::lock_guard<std::recursive_mutex> lock(eventHandlerMutex_);
235     if (eventHandler_) {
236         HILOG_DEBUG("EventHandle is exist,no need to create a new one");
237         return true;
238     }
239     // Create event runner
240     HILOG_INFO("Create eventHandle");
241     if (eventRunner_ == nullptr) {
242         eventRunner_ = EventRunner::Create(GetThreadNameByBundle(bundleName));
243         if (eventRunner_ == nullptr) {
244             HILOG_ERROR("Create event runner Failed");
245             return false;
246         }
247     }
248     // Create event handler
249     eventHandler_ = std::make_shared<EventHandler>(eventRunner_);
250     if (eventHandler_ == nullptr) {
251         HILOG_ERROR("Create event handler failed");
252         return false;
253     }
254 
255     if (needMonitored && !hasMonitor_) {
256         std::weak_ptr<FormRenderRecord> thisWeakPtr(shared_from_this());
257         auto task = [thisWeakPtr]() {
258             auto renderRecord = thisWeakPtr.lock();
259             if (renderRecord == nullptr) {
260                 HILOG_ERROR("null renderRecord");
261                 return;
262             }
263             renderRecord->jsThreadId_ = getproctid();
264             renderRecord->processId_ = getprocpid();
265             HILOG_INFO("Get thread %{public}d and psid %{public}d", renderRecord->jsThreadId_,
266                 renderRecord->processId_);
267         };
268         eventHandler_->PostHighPriorityTask(task, "GotJSThreadId");
269 
270         hasMonitor_.store(true);
271         AddWatchDogThreadMonitor();
272     }
273 
274     return true;
275 }
276 
AddWatchDogThreadMonitor()277 void FormRenderRecord::AddWatchDogThreadMonitor()
278 {
279     HILOG_INFO("add watchDog monitor, bundleName is %{public}s, uid is %{public}s",
280         bundleName_.c_str(), uid_.c_str());
281 
282     auto threadBlockMonitorTask = [weak = weak_from_this()]() {
283         auto renderRecord = weak.lock();
284         if (renderRecord) {
285             renderRecord->Timer();
286         }
287     };
288     OHOS::HiviewDFX::Watchdog::GetInstance().RunPeriodicalTask(RENDERING_BLOCK_MONITOR_PREFIX + bundleName_,
289         threadBlockMonitorTask, THREAD_BLOCK_TIMEOUT);
290 
291     auto memoryMonitorTask = [weak = weak_from_this()]() {
292         auto renderRecord = weak.lock();
293         if (renderRecord) {
294             renderRecord->RuntimeMemoryMonitor();
295         }
296     };
297     OHOS::HiviewDFX::Watchdog::GetInstance().RunPeriodicalTask(MEMORY_MONITOR_PREFIX + bundleName_, memoryMonitorTask,
298         MEMORY_MONITOR_INTERVAL);
299 }
300 
RemoveWatchDogThreadMonitor()301 void FormRenderRecord::RemoveWatchDogThreadMonitor()
302 {
303     HILOG_INFO("remove watchDog monitor, bundleName: %{public}s", bundleName_.c_str());
304     OHOS::HiviewDFX::Watchdog::GetInstance().RemovePeriodicalTask(RENDERING_BLOCK_MONITOR_PREFIX + bundleName_);
305     OHOS::HiviewDFX::Watchdog::GetInstance().RemovePeriodicalTask(MEMORY_MONITOR_PREFIX + bundleName_);
306 }
307 
OnRenderingBlock(const std::string & bundleName)308 void FormRenderRecord::OnRenderingBlock(const std::string &bundleName)
309 {
310     sptr<IFormSupply> formSupplyClient = GetFormSupplyClient();
311 
312     if (formSupplyClient == nullptr) {
313         HILOG_ERROR("null formSupplyClient");
314         return;
315     }
316 
317     formSupplyClient->OnRenderingBlock(bundleName);
318 }
319 
OnNotifyRefreshForm(const int64_t & formId)320 void FormRenderRecord::OnNotifyRefreshForm(const int64_t &formId)
321 {
322     sptr<IFormSupply> formSupplyClient = GetFormSupplyClient();
323 
324     if (formSupplyClient == nullptr) {
325         HILOG_ERROR("null formSupplyClient");
326         return;
327     }
328 
329     formSupplyClient->OnNotifyRefreshForm(formId);
330     HILOG_WARN("Without this form:%{public}" PRId64 "", formId);
331 }
332 
Timer()333 void FormRenderRecord::Timer()
334 {
335     TaskState taskState = RunTask();
336     if (taskState == TaskState::BLOCK) {
337         HILOG_ERROR("FRS block happened when bundleName is %{public}s, uid is %{public}s",
338             bundleName_.c_str(), uid_.c_str());
339         OHOS::HiviewDFX::DfxDumpCatcher dumplog;
340         std::string traceStr;
341         bool ret = dumplog.DumpCatch(processId_, jsThreadId_, traceStr);
342         if (ret) {
343             HILOG_INFO("Print block form's process id %{public}d and thread %{public}d call stack %{public}s",
344                 processId_, jsThreadId_, traceStr.c_str());
345         }
346         FormRenderEventReport::SendBlockFaultEvent(bundleName_, "THREAD_BLOCK_" +
347             std::to_string(THREAD_BLOCK_TIMEOUT) + "ms", traceStr);
348         OnRenderingBlock(bundleName_);
349     }
350 }
351 
RunTask()352 TaskState FormRenderRecord::RunTask()
353 {
354     auto eventHandler = GetEventHandler();
355     if (eventHandler == nullptr) {
356         HILOG_DEBUG("null eventHandler when bundleName %{public}s", bundleName_.c_str());
357         return TaskState::NO_RUNNING;
358     }
359 
360     std::unique_lock<std::mutex> lock(watchDogMutex_);
361     if (!threadIsAlive_) {
362         threadState_->NextState();
363         HILOG_INFO("FRS block happened with threadState is %{public}d when bundleName is %{public}s",
364             threadState_->GetCurrentState(), bundleName_.c_str());
365         DumpEventHandler();
366         return threadState_->IsMaxState() ? TaskState::BLOCK : TaskState::RUNNING;
367     }
368 
369     threadIsAlive_ = false;
370     std::weak_ptr<FormRenderRecord> thisWeakPtr(shared_from_this());
371     auto checkTask = [thisWeakPtr] () {
372         auto renderRecord = thisWeakPtr.lock();
373         if (renderRecord == nullptr) {
374             HILOG_ERROR("null renderRecord");
375             return;
376         }
377 
378         renderRecord->MarkThreadAlive();
379     };
380 
381     if (eventHandler == nullptr) {
382         return TaskState::NO_RUNNING;
383     }
384 
385     if (!eventHandler->PostTask(checkTask, "Watchdog Task", 0, AppExecFwk::EventQueue::Priority::IMMEDIATE)) {
386         HILOG_ERROR("Watchdog checkTask postTask false");
387     }
388 
389     return TaskState::RUNNING;
390 }
391 
DumpEventHandler()392 void FormRenderRecord::DumpEventHandler()
393 {
394     auto eventHandler = GetEventHandler();
395     if (eventHandler == nullptr) {
396         return;
397     }
398 
399     HandlerDumper handlerDumper;
400     eventHandler->Dump(handlerDumper);
401 }
402 
MarkThreadAlive()403 void FormRenderRecord::MarkThreadAlive()
404 {
405     std::unique_lock<std::mutex> lock(watchDogMutex_);
406     threadIsAlive_ = true;
407     threadState_->ResetState();
408 }
409 
MarkRenderFormTaskDone(int32_t renderType)410 void FormRenderRecord::MarkRenderFormTaskDone(int32_t renderType)
411 {
412     if (renderType == Constants::RENDER_FORM) {
413         renderFormTasksNum--;
414     }
415 }
416 
HasRenderFormTask()417 bool FormRenderRecord::HasRenderFormTask()
418 {
419     return renderFormTasksNum > 0;
420 }
421 
UpdateRenderRecord(const FormJsInfo & formJsInfo,const Want & want,const sptr<IRemoteObject> hostRemoteObj)422 int32_t FormRenderRecord::UpdateRenderRecord(const FormJsInfo &formJsInfo, const Want &want,
423     const sptr<IRemoteObject> hostRemoteObj)
424 {
425     auto renderType = want.GetIntParam(Constants::FORM_RENDER_TYPE_KEY, Constants::RENDER_FORM);
426     if (renderType == Constants::RENDER_FORM) {
427         // Manager delegate proxy invalid, do not render form
428         if (!CheckManagerDelegateValid(formJsInfo, want)) {
429             return RENDER_FORM_FAILED;
430         }
431         renderFormTasksNum++;
432         bool formIsVisible = want.GetBoolParam(Constants::FORM_IS_VISIBLE, false);
433         RecordFormVisibility(formJsInfo.formId, formIsVisible);
434     }
435     int32_t formLocation = want.GetIntParam(Constants::FORM_LOCATION_KEY, -1);
436     FormLocationInfo location = { formJsInfo.formName, formLocation };
437     RecordFormLocation(formJsInfo.formId, location);
438     {
439         // Some resources need to be initialized in a JS thread
440         if (!CheckEventHandler(true, formJsInfo.isDynamic)) {
441             HILOG_ERROR("null eventHandler_ ");
442             return RENDER_FORM_FAILED;
443         }
444         std::shared_ptr<EventHandler> eventHandler = GetEventHandler();
445 
446         sptr<IFormSupply> formSupplyClient = GetFormSupplyClient();
447         if (formSupplyClient == nullptr) {
448             HILOG_ERROR("null formSupplyClient");
449             return RENDER_FORM_FAILED;
450         }
451 
452         UpdateFormRequest(formJsInfo, want);
453 
454         std::weak_ptr<FormRenderRecord> thisWeakPtr(shared_from_this());
455         auto task = [thisWeakPtr, formJsInfo, want, formSupplyClient, renderType]() {
456             auto renderRecord = thisWeakPtr.lock();
457             if (renderRecord == nullptr) {
458                 HILOG_ERROR("null renderRecord, formId:%{public}" PRId64, formJsInfo.formId);
459                 return;
460             }
461             renderRecord->HandleUpdateInJsThread(formJsInfo, want);
462             renderRecord->MarkRenderFormTaskDone(renderType);
463             FormRenderStatusTaskMgr::GetInstance().OnRenderFormDone(formJsInfo.formId,
464                 FormFsmEvent::RENDER_FORM_DONE, formSupplyClient);
465             HILOG_INFO("HandleUpdateInJsThread end");
466         };
467         if (eventHandler == nullptr) {
468             HILOG_ERROR("null eventHandler_ ");
469             return RENDER_FORM_FAILED;
470         }
471         eventHandler->PostTask(task, "UpdateRenderRecord");
472     }
473 
474     if (hostRemoteObj == nullptr) {
475         HILOG_WARN("null hostRemoteObj");
476         return ERR_OK;
477     }
478     return AddHostByFormId(formJsInfo.formId, hostRemoteObj);
479 }
480 
DeleteRenderRecord(int64_t formId,const std::string & compId,const sptr<IRemoteObject> hostRemoteObj,bool & isRenderGroupEmpty)481 void FormRenderRecord::DeleteRenderRecord(int64_t formId, const std::string &compId,
482     const sptr<IRemoteObject> hostRemoteObj, bool &isRenderGroupEmpty)
483 {
484     // Some resources need to be deleted in a JS thread
485     HILOG_INFO("Delete some resources formId:%{public}" PRId64 ",%{public}s", formId, compId.c_str());
486     std::shared_ptr<EventHandler> eventHandler = GetEventHandler();
487     if (eventHandler == nullptr) {
488         HILOG_ERROR("null eventHandler");
489         DeleteFormRequest(formId, compId);
490         RecordFormVisibility(formId, false);
491         return;
492     }
493 
494     auto task = [weak = weak_from_this(), formId, compId, &isRenderGroupEmpty]() {
495         auto renderRecord = weak.lock();
496         if (renderRecord == nullptr) {
497             HILOG_ERROR("null renderRecord");
498             return;
499         }
500 
501         FormMemoryGuard memoryGuard;
502         isRenderGroupEmpty = renderRecord->HandleDeleteInJsThread(formId, compId);
503         renderRecord->DeleteFormRequest(formId, compId);
504     };
505 
506     if (hostRemoteObj != nullptr) {
507         DeleteHostRemoteObjByFormId(formId, hostRemoteObj);
508     }
509     if (eventHandler == nullptr) {
510         return;
511     }
512     eventHandler->PostSyncTask(task, "DeleteRenderRecord");
513 }
514 
IsEmpty()515 bool FormRenderRecord::IsEmpty()
516 {
517     bool rendererEmpty = false;
518     bool formRequestsEmpty = false;
519     {
520         std::lock_guard<std::mutex> lock(formRendererGroupMutex_);
521         rendererEmpty = formRendererGroupMap_.empty();
522     }
523     {
524         std::lock_guard<std::mutex> lock(formRequestsMutex_);
525         formRequestsEmpty = formRequests_.empty();
526     }
527     return rendererEmpty && formRequestsEmpty;
528 }
529 
GetUid() const530 std::string FormRenderRecord::GetUid() const
531 {
532     return uid_;
533 }
534 
CreateRuntime(const FormJsInfo & formJsInfo)535 bool FormRenderRecord::CreateRuntime(const FormJsInfo &formJsInfo)
536 {
537     if (runtime_) {
538         HILOG_DEBUG("runtime is exist,no need to create a new one");
539         return true;
540     }
541 
542     HILOG_INFO("Create a new runtime");
543     if (eventRunner_ == nullptr) {
544         HILOG_ERROR("null eventRunner_");
545         return false;
546     }
547 
548     AbilityRuntime::Runtime::Options options;
549     options.bundleName = formJsInfo.bundleName;
550     options.codePath = Constants::LOCAL_CODE_PATH;
551     BundleInfo bundleInfo;
552     options.eventRunner = eventRunner_;
553     options.hapPath = formJsInfo.jsFormCodePath;
554     options.loadAce = true;
555     options.isBundle = true;
556     options.isUnique = true;
557     options.moduleCheckerDelegate = std::make_shared<FormModuleChecker>();
558 
559     SetPkgContextInfoMap(formJsInfo, options);
560 
561     runtime_ = AbilityRuntime::Runtime::Create(options);
562     if (runtime_ == nullptr) {
563         HILOG_ERROR("Create runtime Failed");
564         return false;
565     }
566     hapPath_ = formJsInfo.jsFormCodePath;
567     RegisterUncatchableErrorHandler();
568     return true;
569 }
570 
UpdateRuntime(const FormJsInfo & formJsInfo)571 bool FormRenderRecord::UpdateRuntime(const FormJsInfo &formJsInfo)
572 {
573     if (IsFormContextExist(formJsInfo)) {
574         HILOG_WARN("context is exist. %{public}s", formJsInfo.bundleName.c_str());
575         return false;
576     }
577     if (!runtime_) {
578         HILOG_ERROR("runtime is not exist. %{public}s", formJsInfo.bundleName.c_str());
579         return false;
580     }
581     std::string moduleName = formJsInfo.moduleName;
582     HILOG_INFO("update runtime for bundle:%{public}s, module %{public}s",
583         formJsInfo.bundleName.c_str(), moduleName.c_str());
584     AbilityRuntime::Runtime::Options options;
585     SetPkgContextInfoMap(formJsInfo, options);
586     auto contextInfo = options.pkgContextInfoJsonStringMap.find(moduleName);
587     if (contextInfo != options.pkgContextInfoJsonStringMap.end()) {
588         auto pkgNameInfo = options.packageNameList.find(moduleName);
589         std::string packageName;
590         if (pkgNameInfo != options.packageNameList.end()) {
591             packageName = pkgNameInfo->second;
592         }
593         if (runtime_->GetLanguage() == AbilityRuntime::Runtime::Language::JS) {
594             (static_cast<AbilityRuntime::JsRuntime&>(*runtime_)).SetPkgContextInfoJson(moduleName, contextInfo->second,
595                 packageName);
596             HILOG_INFO("%{public}s load components of new module %{public}s",
597                 formJsInfo.bundleName.c_str(), moduleName.c_str());
598             (static_cast<AbilityRuntime::JsRuntime&>(*runtime_)).ReloadFormComponent();
599         }
600     }
601     return true;
602 }
603 
SetPkgContextInfoMap(const FormJsInfo & formJsInfo,AbilityRuntime::Runtime::Options & options)604 bool FormRenderRecord::SetPkgContextInfoMap(const FormJsInfo &formJsInfo, AbilityRuntime::Runtime::Options &options)
605 {
606     std::map<std::string, std::string> pkgContextInfoJsonStringMap;
607     for (auto modulePkgNamePair : formJsInfo.modulePkgNameMap) {
608         nlohmann::json moduleInfos = nlohmann::json::parse(modulePkgNamePair.second, nullptr, false);
609         if (moduleInfos.is_discarded()) {
610             HILOG_ERROR("fail parse modulePkgNamePair");
611             continue;
612         }
613         std::string pkgName = "";
614         std::string hapPath = "";
615         if (moduleInfos.contains(Constants::MODULE_PKG_NAME_KEY) &&
616             moduleInfos.at(Constants::MODULE_PKG_NAME_KEY).is_string()) {
617             pkgName = moduleInfos[Constants::MODULE_PKG_NAME_KEY].get<std::string>();
618             options.packageNameList[modulePkgNamePair.first] = pkgName;
619         }
620         if (moduleInfos.contains(Constants::MODULE_HAP_PATH_KEY) &&
621             moduleInfos.at(Constants::MODULE_HAP_PATH_KEY).is_string()) {
622             hapPath = moduleInfos[Constants::MODULE_HAP_PATH_KEY].get<std::string>();
623             pkgContextInfoJsonStringMap[modulePkgNamePair.first] = hapPath;
624         }
625         HILOG_INFO("SetPkgContextInfoMap module:%{public}s, pkgName:%{public}s, hapPath:%{public}s",
626             modulePkgNamePair.first.c_str(), pkgName.c_str(), hapPath.c_str());
627     }
628     if (!pkgContextInfoJsonStringMap.empty()) {
629         HILOG_INFO("set pkgContextInfoJsonStringMap for %{public}s", formJsInfo.bundleName.c_str());
630         options.pkgContextInfoJsonStringMap = pkgContextInfoJsonStringMap;
631     }
632     return true;
633 }
634 
SetConfiguration(const std::shared_ptr<OHOS::AppExecFwk::Configuration> & config)635 void FormRenderRecord::SetConfiguration(const std::shared_ptr<OHOS::AppExecFwk::Configuration>& config)
636 {
637     if (configuration_) {
638         auto checkConfigItem = {SYSTEM_COLORMODE, SYSTEM_LANGUAGE, SYSTEM_FONT_SIZE_SCALE, SYSTEM_FONT_WEIGHT_SCALE};
639         for (const auto& item: checkConfigItem) {
640             std::string value = config->GetItem(item);
641             if (!value.empty()) {
642                 configuration_->AddItem(item, value);
643             }
644         }
645     } else {
646         configuration_ = config;
647     }
648 }
649 
GetContext(const FormJsInfo & formJsInfo,const Want & want)650 std::shared_ptr<AbilityRuntime::Context> FormRenderRecord::GetContext(const FormJsInfo &formJsInfo, const Want &want)
651 {
652     {
653         std::lock_guard<std::mutex> lock(contextsMapMutex_);
654         auto iter = contextsMapForModuleName_.find(GenerateContextKey(formJsInfo));
655         if (iter != contextsMapForModuleName_.end()) {
656             if (iter->second == nullptr) {
657                 HILOG_WARN("null Context, bundle name is %{public}s", formJsInfo.bundleName.c_str());
658                 return nullptr;
659             }
660             auto applicationInfo = iter->second->GetApplicationInfo();
661             if (applicationInfo != nullptr) {
662                 uint32_t apiCompatibleVersion = static_cast<uint32_t>(
663                     want.GetIntParam(Constants::FORM_COMPATIBLE_VERSION_KEY, 0));
664                 if (apiCompatibleVersion != 0) {
665                     applicationInfo->apiCompatibleVersion = apiCompatibleVersion;
666                 }
667                 HILOG_INFO("GetContext bundleName %{public}s, apiCompatibleVersion = %{public}d",
668                     formJsInfo.bundleName.c_str(), applicationInfo->apiCompatibleVersion);
669             }
670 
671             std::shared_ptr<OHOS::AppExecFwk::Configuration> config = iter->second->GetConfiguration();
672             if (config != nullptr && configuration_ != nullptr) {
673                 std::string colorMode = configuration_->GetItem(SYSTEM_COLORMODE);
674                 std::string languageTag = configuration_->GetItem(SYSTEM_LANGUAGE);
675                 config->AddItem(SYSTEM_COLORMODE, colorMode);
676                 config->AddItem(SYSTEM_LANGUAGE, languageTag);
677             }
678             return iter->second;
679         }
680     }
681 
682     return CreateContext(formJsInfo, want);
683 }
684 
CreateContext(const FormJsInfo & formJsInfo,const Want & want)685 std::shared_ptr<AbilityRuntime::Context> FormRenderRecord::CreateContext(const FormJsInfo &formJsInfo, const Want &want)
686 {
687     HILOG_INFO("Create a new context");
688     auto context = std::make_shared<AbilityRuntime::ContextImpl>();
689     if (context == nullptr) {
690         HILOG_ERROR("Create context failed");
691         return nullptr;
692     }
693 
694     context->SetConfiguration(configuration_);
695     AppExecFwk::HapModuleInfo hapModuleInfo;
696     hapModuleInfo.name = formJsInfo.moduleName;
697     hapModuleInfo.hapPath = formJsInfo.jsFormCodePath;
698     hapModuleInfo.compileMode = static_cast<CompileMode>(want.GetIntParam(Constants::FORM_COMPILE_MODE_KEY,
699         static_cast<int32_t>(CompileMode::ES_MODULE)));
700     context->InitHapModuleInfo(hapModuleInfo);
701     auto applicationInfo = std::make_shared<AppExecFwk::ApplicationInfo>();
702     applicationInfo->bundleName = formJsInfo.bundleName;
703     applicationInfo->apiCompatibleVersion = static_cast<uint32_t>(want.GetIntParam(
704         Constants::FORM_COMPATIBLE_VERSION_KEY, 0));
705     applicationInfo->apiTargetVersion = static_cast<int32_t>(want.GetIntParam(
706         Constants::FORM_TARGET_VERSION_KEY, 0));
707     context->SetApplicationInfo(applicationInfo);
708     HILOG_DEBUG("bundleName is %{public}s, moduleName is %{public}s",
709         formJsInfo.bundleName.c_str(), formJsInfo.moduleName.c_str());
710 
711     std::lock_guard<std::mutex> lock(contextsMapMutex_);
712     contextsMapForModuleName_.emplace(GenerateContextKey(formJsInfo), context);
713     return context;
714 }
715 
GetFormRendererGroup(const FormJsInfo & formJsInfo,const std::shared_ptr<AbilityRuntime::Context> & context,const std::shared_ptr<AbilityRuntime::Runtime> & runtime)716 std::shared_ptr<Ace::FormRendererGroup> FormRenderRecord::GetFormRendererGroup(const FormJsInfo &formJsInfo,
717     const std::shared_ptr<AbilityRuntime::Context> &context, const std::shared_ptr<AbilityRuntime::Runtime> &runtime)
718 {
719     HILOG_INFO("Get formRendererGroup");
720     if (GetEventHandlerNeedReset()) {
721         return nullptr;
722     }
723     std::lock_guard<std::mutex> lock(formRendererGroupMutex_);
724     auto key = formJsInfo.formId;
725     auto iter = formRendererGroupMap_.find(key);
726     if (iter != formRendererGroupMap_.end()) {
727         return iter->second;
728     }
729 
730     auto formRendererGroup = CreateFormRendererGroupLock(formJsInfo, context, runtime);
731     if (formRendererGroup != nullptr) {
732         HILOG_INFO("formRendererGroupMap emplace formId:%{public}s", std::to_string(key).c_str());
733         formRendererGroupMap_.emplace(key, formRendererGroup);
734         RecordFormVisibility(key, true);
735     }
736     return formRendererGroup;
737 }
738 
CreateFormRendererGroupLock(const FormJsInfo & formJsInfo,const std::shared_ptr<AbilityRuntime::Context> & context,const std::shared_ptr<AbilityRuntime::Runtime> & runtime)739 std::shared_ptr<Ace::FormRendererGroup> FormRenderRecord::CreateFormRendererGroupLock(const FormJsInfo &formJsInfo,
740     const std::shared_ptr<AbilityRuntime::Context> &context, const std::shared_ptr<AbilityRuntime::Runtime> &runtime)
741 {
742     HILOG_INFO("Create formRendererGroup");
743     std::shared_ptr<EventHandler> eventHandler = GetEventHandler();
744     if (eventHandler == nullptr) {
745         return nullptr;
746     }
747     auto formRendererGroup = Ace::FormRendererGroup::Create(context, runtime, eventHandler);
748     if (formRendererGroup == nullptr) {
749         HILOG_ERROR("Create formRendererGroup failed");
750         return nullptr;
751     }
752     return formRendererGroup;
753 }
754 
UpdateFormRequest(const FormJsInfo & formJsInfo,const Want & want)755 void FormRenderRecord::UpdateFormRequest(const FormJsInfo &formJsInfo, const Want &want)
756 {
757     auto renderType = want.GetIntParam(Constants::FORM_RENDER_TYPE_KEY, Constants::RENDER_FORM);
758     HILOG_DEBUG("renderType is %{public}d", renderType);
759     if (renderType == Constants::RENDER_FORM) {
760         AddFormRequest(formJsInfo, want);
761         return;
762     }
763 
764     std::unordered_map<std::string, Ace::FormRequest> formRequests;
765     if (!GetFormRequestByFormId(formJsInfo.formId, formRequests)) {
766         return;
767     }
768 
769     for (const auto &iter : formRequests) {
770         auto formRequest = iter.second;
771         MergeFormData(formRequest, formJsInfo);
772         AddFormRequest(formJsInfo.formId, formRequest);
773     }
774 }
775 
HandleUpdateInJsThread(const FormJsInfo & formJsInfo,const Want & want)776 int32_t FormRenderRecord::HandleUpdateInJsThread(const FormJsInfo &formJsInfo, const Want &want)
777 {
778     HILOG_INFO("Update record in js thread, formId:%{public}s", std::to_string(formJsInfo.formId).c_str());
779     bool ret = BeforeHandleUpdateForm(formJsInfo);
780     if (!ret) {
781         HILOG_ERROR("Handle Update Form prepare failed");
782         return ERR_APPEXECFWK_FORM_RUNTIME_FAILED;
783     }
784 
785     return HandleUpdateForm(formJsInfo, want);
786 }
787 
BeforeHandleUpdateForm(const FormJsInfo & formJsInfo)788 bool FormRenderRecord::BeforeHandleUpdateForm(const FormJsInfo &formJsInfo)
789 {
790     MarkThreadAlive();
791     if (runtime_ == nullptr) {
792         if (!CreateRuntime(formJsInfo)) {
793             HILOG_ERROR("Create runtime failed");
794             return false;
795         }
796     } else {
797         UpdateRuntime(formJsInfo);
798     }
799     return true;
800 }
801 
HandleUpdateForm(const FormJsInfo & formJsInfo,const Want & want)802 int32_t FormRenderRecord::HandleUpdateForm(const FormJsInfo &formJsInfo, const Want &want)
803 {
804     auto renderType = want.GetIntParam(Constants::FORM_RENDER_TYPE_KEY, Constants::RENDER_FORM);
805     HILOG_DEBUG("renderType is %{public}d", renderType);
806     if (renderType == Constants::RENDER_FORM) {
807         AddRenderer(formJsInfo, want);
808         return ERR_OK;
809     }
810 
811     std::unordered_map<std::string, Ace::FormRequest> formRequests;
812     if (!GetFormRequestByFormId(formJsInfo.formId, formRequests)) {
813         OnNotifyRefreshForm(formJsInfo.formId);
814         return ERR_APPEXECFWK_FORM_NOT_EXIST_FORM_REQUEST;
815     }
816     std::string compMaxId = "0";
817     for (const auto& iter : formRequests) {
818         if (iter.second.compId > compMaxId) {
819             compMaxId = iter.second.compId;
820         }
821     }
822 
823     bool isDynamicFormNeedRecover = false;
824     for (const auto& iter : formRequests) {
825         auto formRequest = iter.second;
826         if (!formRequest.hasRelease) {
827             UpdateRenderer(formJsInfo);
828             continue;
829         }
830         if (formJsInfo.isDynamic) {
831             isDynamicFormNeedRecover = true;
832             continue;
833         }
834         if (compMaxId == formRequest.compId) {
835             AddRenderer(formJsInfo, formRequest.want);
836             UpdateFormRequestReleaseState(formJsInfo.formId, formRequest.compId, false);
837         }
838     }
839 
840     if (isDynamicFormNeedRecover) {
841         std::string statusData = want.GetStringParam(Constants::FORM_STATUS_DATA);
842         bool isHandleClickEvent = false;
843         HandleRecoverForm(formJsInfo, statusData, isHandleClickEvent);
844     }
845 
846     return ERR_OK;
847 }
848 
MergeFormData(Ace::FormRequest & formRequest,const FormJsInfo & formJsInfo)849 void FormRenderRecord::MergeFormData(Ace::FormRequest &formRequest, const FormJsInfo &formJsInfo)
850 {
851     FormProviderData formProviderData = FormProviderData(formRequest.formJsInfo.formData, true);
852     nlohmann::json newFormData = formJsInfo.formProviderData.GetData();
853     formProviderData.MergeData(newFormData);
854 
855     std::map<std::string, sptr<FormAshmem>> imageMap = formRequest.formJsInfo.imageDataMap;
856     formRequest.formJsInfo = formJsInfo;
857     //if imageDataMap of formJsInfo is empty, do not replace
858     if (formJsInfo.imageDataMap.size() == 0) {
859         formRequest.formJsInfo.imageDataMap = imageMap;
860     }
861     formRequest.formJsInfo.formData = formProviderData.GetDataString();
862 }
863 
AddRenderer(const FormJsInfo & formJsInfo,const Want & want)864 void FormRenderRecord::AddRenderer(const FormJsInfo &formJsInfo, const Want &want)
865 {
866     auto context = GetContext(formJsInfo, want);
867     if (context == nullptr) {
868         HILOG_ERROR("Create Context failed");
869         return;
870     }
871 
872     auto formRendererGroup = GetFormRendererGroup(formJsInfo, context, runtime_);
873     if (formRendererGroup == nullptr) {
874         HILOG_ERROR("Create formRendererGroup failed");
875         return;
876     }
877     formRendererGroup->AddForm(want, formJsInfo);
878     HILOG_INFO("AddForm formId:%{public}s", std::to_string(formJsInfo.formId).c_str());
879 }
880 
UpdateRenderer(const FormJsInfo & formJsInfo)881 void FormRenderRecord::UpdateRenderer(const FormJsInfo &formJsInfo)
882 {
883     std::lock_guard<std::mutex> lock(formRendererGroupMutex_);
884     if (auto search = formRendererGroupMap_.find(formJsInfo.formId);
885         search != formRendererGroupMap_.end()) {
886         auto group = search->second;
887         group->UpdateForm(formJsInfo);
888         HILOG_INFO("UpdateForm formId:%{public}s", std::to_string(formJsInfo.formId).c_str());
889     } else {
890         HILOG_ERROR("UpdateForm failed:%{public}s", std::to_string(formJsInfo.formId).c_str());
891     }
892 }
893 
HandleDeleteInJsThread(int64_t formId,const std::string & compId)894 bool FormRenderRecord::HandleDeleteInJsThread(int64_t formId, const std::string &compId)
895 {
896     HILOG_INFO("Delete some resources in js thread");
897     MarkThreadAlive();
898     {
899         std::lock_guard<std::mutex> lock(formRendererGroupMutex_);
900         auto search = formRendererGroupMap_.find(formId);
901         if (search == formRendererGroupMap_.end()) {
902             HILOG_ERROR("invalid FormRendererGroup");
903             return false;
904         }
905         if (!search->second) {
906             HILOG_ERROR("FormRendererGroup was founded but null");
907             return false;
908         }
909         if (!compId.empty()) {
910             search->second->DeleteForm(compId);
911             RecordFormVisibility(formId, false);
912             HILOG_ERROR("HandleDeleteInJsThread compid is %{public}s", compId.c_str());
913             if (search->second->IsFormRequestsEmpty()) {
914                 formRendererGroupMap_.erase(formId);
915                 DeleteFormLocation(formId);
916             }
917             return false;
918         }
919         search->second->DeleteForm();
920         formRendererGroupMap_.erase(formId);
921         DeleteFormLocation(formId);
922     }
923     RemoveHostByFormId(formId);
924     return true;
925 }
926 
CheckEventHandler(bool createThead,bool needMonitored)927 bool FormRenderRecord::CheckEventHandler(bool createThead, bool needMonitored)
928 {
929     if (eventHandler_ == nullptr && createThead) {
930         CreateEventHandler(bundleName_, needMonitored);
931     }
932 
933     return eventHandler_ != nullptr;
934 }
935 
AddFormRequest(const FormJsInfo & formJsInfo,const Want & want)936 void FormRenderRecord::AddFormRequest(const FormJsInfo &formJsInfo, const Want &want)
937 {
938     auto compId = want.GetStringParam(FORM_RENDERER_COMP_ID);
939     HILOG_INFO("AddFormRequest formId: %{public}s, compId: %{public}s, formJsInfo.formData.size: %{public}zu.",
940         std::to_string(formJsInfo.formId).c_str(),
941         compId.c_str(),
942         formJsInfo.formData.size());
943     if (compId.empty()) {
944         return;
945     }
946 
947     std::lock_guard<std::mutex> lock(formRequestsMutex_);
948     Ace::FormRequest formRequest;
949     formRequest.compId = compId;
950     formRequest.want = want;
951     formRequest.want.SetParam(Constants::FORM_RENDER_TYPE_KEY, Constants::RENDER_FORM);
952     formRequest.isDynamic = formJsInfo.isDynamic;
953     formRequest.formJsInfo = formJsInfo;
954     auto iter = formRequests_.find(formJsInfo.formId);
955     if (iter == formRequests_.end()) {
956         std::unordered_map<std::string, Ace::FormRequest> formRequests;
957         formRequests.emplace(compId, formRequest);
958         formRequests_.emplace(formJsInfo.formId, formRequests);
959         return;
960     }
961 
962     auto innerIter = iter->second.find(compId);
963     if (innerIter != iter->second.end()) {
964         iter->second.erase(innerIter);
965     }
966     iter->second.emplace(compId, formRequest);
967 }
968 
AddFormRequest(int64_t formId,Ace::FormRequest & formRequest)969 void FormRenderRecord::AddFormRequest(int64_t formId, Ace::FormRequest &formRequest)
970 {
971     HILOG_INFO("AddFormRequest by FormRequest formId: %{public}s, compId: %{public}s, formData.size: %{public}zu",
972         std::to_string(formId).c_str(),
973         formRequest.compId.c_str(),
974         formRequest.formJsInfo.formData.size());
975     std::lock_guard<std::mutex> lock(formRequestsMutex_);
976     auto iter = formRequests_.find(formId);
977     if (iter == formRequests_.end()) {
978         std::unordered_map<std::string, Ace::FormRequest> formRequests;
979         formRequests.emplace(formRequest.compId, formRequest);
980         formRequests_.emplace(formId, formRequests);
981         return;
982     }
983 
984     auto innerIter = iter->second.find(formRequest.compId);
985     if (innerIter != iter->second.end()) {
986         iter->second.erase(innerIter);
987     }
988     iter->second.emplace(formRequest.compId, formRequest);
989 }
990 
DeleteFormRequest(int64_t formId,const std::string & compId)991 void FormRenderRecord::DeleteFormRequest(int64_t formId, const std::string &compId)
992 {
993     bool isRequestEmpty = false;
994     {
995         std::lock_guard<std::mutex> lock(formRequestsMutex_);
996         auto iter = formRequests_.find(formId);
997         if (iter == formRequests_.end()) {
998             HILOG_ERROR("invalid request,formId:%{public}" PRId64, formId);
999             return;
1000         }
1001 
1002         if (compId.empty()) {
1003             formRequests_.erase(iter);
1004             isRequestEmpty = true;
1005         } else {
1006             auto innerIter = iter->second.find(compId);
1007             if (innerIter != iter->second.end()) {
1008                 iter->second.erase(innerIter);
1009             }
1010             if (iter->second.empty()) {
1011                 formRequests_.erase(iter);
1012                 isRequestEmpty = true;
1013             }
1014         }
1015     }
1016     if (isRequestEmpty) {
1017         DeleteRecycledFormCompIds(formId);
1018     }
1019     HILOG_INFO("delete request formId:%{public}" PRId64 " compId:%{public}s request empty:%{public}d",
1020         formId, compId.c_str(), isRequestEmpty);
1021 }
1022 
UpdateFormRequestReleaseState(int64_t formId,const std::string & compId,bool hasRelease)1023 void FormRenderRecord::UpdateFormRequestReleaseState(
1024     int64_t formId, const std::string &compId, bool hasRelease)
1025 {
1026     HILOG_INFO("Update ReleaseState formId:%{public}" PRId64 ", compId:%{public}s, hasRelease:%{public}d",
1027         formId, compId.c_str(), hasRelease);
1028     std::lock_guard<std::mutex> lock(formRequestsMutex_);
1029     auto iter = formRequests_.find(formId);
1030     if (iter == formRequests_.end()) {
1031         HILOG_ERROR("invalid request,formId:%{public}" PRId64, formId);
1032         return;
1033     }
1034 
1035     auto innerIter = iter->second.find(compId);
1036     if (innerIter == iter->second.end()) {
1037         HILOG_ERROR("invalid compId,formId:%{public}" PRId64, formId);
1038         return;
1039     }
1040 
1041     for (auto& formRequest : iter->second) {
1042         formRequest.second.hasRelease = hasRelease;
1043     }
1044 }
1045 
ReleaseRenderer(int64_t formId,const std::string & compId,bool & isRenderGroupEmpty)1046 void FormRenderRecord::ReleaseRenderer(
1047     int64_t formId, const std::string &compId, bool &isRenderGroupEmpty)
1048 {
1049     HILOG_INFO("Release renderer which formId:%{public}s, compId:%{public}s start.",
1050         std::to_string(formId).c_str(), compId.c_str());
1051     std::shared_ptr<EventHandler> eventHandler = GetEventHandler();
1052     if (eventHandler == nullptr) {
1053         HILOG_ERROR("null eventHandler");
1054         return;
1055     }
1056 
1057     auto task = [weak = weak_from_this(), formId, compId, &isRenderGroupEmpty]() {
1058         auto renderRecord = weak.lock();
1059         if (renderRecord == nullptr) {
1060             HILOG_ERROR("null renderRecord");
1061             return;
1062         }
1063 
1064         FormMemoryGuard memoryGuard;
1065         bool ret = renderRecord->HandleReleaseRendererInJsThread(formId, compId, isRenderGroupEmpty);
1066         if (ret) {
1067             renderRecord->UpdateFormRequestReleaseState(formId, compId, true);
1068         } else {
1069             HILOG_ERROR("release renderer error, skip update state, formId:%{public}" PRId64, formId);
1070         }
1071     };
1072     eventHandler->PostSyncTask(task, "ReleaseRenderer");
1073 }
1074 
HandleReleaseRendererInJsThread(int64_t formId,const std::string & compId,bool & isRenderGroupEmpty)1075 bool FormRenderRecord::HandleReleaseRendererInJsThread(
1076     int64_t formId, const std::string &compId, bool &isRenderGroupEmpty)
1077 {
1078     HILOG_INFO("Release renderer which formId:%{public}s, compId:%{public}s in js thread.",
1079         std::to_string(formId).c_str(), compId.c_str());
1080     MarkThreadAlive();
1081     if (compId.empty()) {
1082         HILOG_ERROR("compId empty");
1083         return false;
1084     }
1085 
1086     std::pair<std::vector<std::string>, std::string> compIds;
1087     {
1088         std::lock_guard<std::mutex> lock(formRendererGroupMutex_);
1089         auto search = formRendererGroupMap_.find(formId);
1090         if (search == formRendererGroupMap_.end()) {
1091             HILOG_ERROR("invalid rendererGroup");
1092             return false;
1093         }
1094 
1095         if (!search->second) {
1096             HILOG_ERROR("null rendererGroup");
1097             return false;
1098         }
1099 
1100         compIds = search->second->GetOrderedAndCurrentCompIds();
1101         search->second->DeleteForm();
1102         formRendererGroupMap_.erase(formId);
1103         DeleteFormLocation(formId);
1104         isRenderGroupEmpty = formRendererGroupMap_.empty();
1105     }
1106     DeleteRecycledFormCompIds(formId);
1107     InsertRecycledFormCompIds(formId, compIds);
1108     return true;
1109 }
1110 
Release()1111 void FormRenderRecord::Release()
1112 {
1113     HILOG_INFO("Release runtime and eventHandler");
1114     std::shared_ptr<EventHandler> eventHandler = eventHandler_;
1115     std::shared_ptr<EventRunner> eventRunner = eventRunner_;
1116     {
1117         std::lock_guard<std::recursive_mutex> lock(eventHandlerMutex_);
1118         if (eventHandler_ == nullptr) {
1119             HILOG_INFO("null eventHandler");
1120             return;
1121         }
1122         eventHandler_ = nullptr;
1123         eventRunner_ = nullptr;
1124     }
1125     auto syncTask = [renderRecord = this]() {
1126         if (renderRecord == nullptr) {
1127             HILOG_ERROR("null renderRecord");
1128             return;
1129         }
1130         renderRecord->HandleReleaseInJsThread();
1131     };
1132     eventHandler->PostSyncTask(syncTask, "HandleReleaseInJsThread");
1133     if (eventRunner) {
1134         eventRunner->Stop();
1135         eventRunner.reset();
1136     }
1137 
1138     eventHandler.reset();
1139 
1140     std::lock_guard<std::mutex> lock(contextsMapMutex_);
1141     contextsMapForModuleName_.clear();
1142 }
1143 
HandleReleaseInJsThread()1144 void FormRenderRecord::HandleReleaseInJsThread()
1145 {
1146     if (runtime_) {
1147         runtime_->ForceFullGC();
1148         runtime_.reset();
1149     }
1150     ReleaseHapFileHandle();
1151 }
1152 
RecoverFormsByConfigUpdate(std::vector<int64_t> & formIds,const sptr<IFormSupply> & formSupplyClient)1153 void FormRenderRecord::RecoverFormsByConfigUpdate(std::vector<int64_t> &formIds,
1154     const sptr<IFormSupply> &formSupplyClient)
1155 {
1156     if (formSupplyClient == nullptr) {
1157         HILOG_ERROR("null formSupplyClient");
1158         return;
1159     }
1160 
1161     if (formIds.empty()) {
1162         HILOG_INFO("empty needRecoverFormIds");
1163         return;
1164     }
1165 
1166     formSupplyClient->OnRecoverFormsByConfigUpdate(formIds);
1167 }
1168 
ReAddAllRecycledForms(const sptr<IFormSupply> & formSupplyClient)1169 void FormRenderRecord::ReAddAllRecycledForms(const sptr<IFormSupply> &formSupplyClient)
1170 {
1171     HILOG_INFO("ReAdd all recycled forms start");
1172     if (!CheckEventHandler(false, true)) {
1173         HILOG_ERROR("CheckEventHandler failed");
1174         return;
1175     }
1176 
1177     std::vector<int64_t> formIds;
1178     std::lock_guard<std::mutex> lock(formRequestsMutex_);
1179     for (const auto& formRequests : formRequests_) {
1180         for (const auto& formRequest : formRequests.second) {
1181             if (!formRequest.second.hasRelease) {
1182                 continue;
1183             }
1184 
1185             if (formRequest.second.isDynamic) {
1186                 formIds.push_back(formRequest.second.formJsInfo.formId);
1187                 continue;
1188             }
1189 
1190             std::weak_ptr<FormRenderRecord> thisWeakPtr(shared_from_this());
1191             auto task = [thisWeakPtr, formJsInfo = formRequest.second.formJsInfo, want = formRequest.second.want]() {
1192                 auto renderRecord = thisWeakPtr.lock();
1193                 if (renderRecord) {
1194                     renderRecord->HandleUpdateInJsThread(formJsInfo, want);
1195                 }
1196             };
1197             eventHandler_->PostTask(task, "ReAddAllRecycledForms");
1198         }
1199     }
1200 
1201     RecoverFormsByConfigUpdate(formIds, formSupplyClient);
1202 
1203     HILOG_INFO("ReAdd all recycled forms end");
1204 }
1205 
PostReAddRecycledForms(const FormJsInfo & formJsInfo,const Want & want)1206 void FormRenderRecord::PostReAddRecycledForms(const FormJsInfo &formJsInfo, const Want &want)
1207 {
1208     std::weak_ptr<FormRenderRecord> thisWeakPtr(shared_from_this());
1209     auto task = [thisWeakPtr, formJsInfo, newWant = want]() {
1210         auto renderRecord = thisWeakPtr.lock();
1211         if (renderRecord) {
1212             int32_t ret = renderRecord->HandleUpdateInJsThread(formJsInfo, newWant);
1213             if (ret != ERR_OK) {
1214                 FormRenderEventReport::SendFormFailedEvent(FormEventName::RELOAD_FORM_FAILED,
1215                     formJsInfo.formId,
1216                     formJsInfo.bundleName,
1217                     formJsInfo.formName,
1218                     static_cast<int32_t>(ReloadFormErrorType::RELOAD_FORM_UPDATE_FORM_ERROR),
1219                     ret);
1220             }
1221         }
1222     };
1223     if (eventHandler_ == nullptr) {
1224         HILOG_ERROR("null eventHandler_");
1225         return;
1226     }
1227     eventHandler_->PostTask(task, "ReAddRecycledForms");
1228 }
1229 
ReAddRecycledForms(const std::vector<FormJsInfo> & formJsInfos)1230 int32_t FormRenderRecord::ReAddRecycledForms(const std::vector<FormJsInfo> &formJsInfos)
1231 {
1232     HILOG_INFO("ReAdd recycled forms start");
1233     if (!CheckEventHandler(false, true)) {
1234         HILOG_ERROR("CheckEventHandler failed");
1235         return ERR_APPEXECFWK_FORM_EVENT_HANDLER_NULL;
1236     }
1237 
1238     for (const auto &form : formJsInfos) {
1239         std::unordered_map<std::string, Ace::FormRequest> formRequests;
1240         if (!GetFormRequestByFormId(form.formId, formRequests)) {
1241             continue;
1242         }
1243 
1244         for (const auto &formRequest : formRequests) {
1245             if (!formRequest.second.hasRelease) {
1246                 continue;
1247             }
1248 
1249             UpdateFormRequest(form, formRequest.second.want);
1250             PostReAddRecycledForms(form, formRequest.second.want);
1251         }
1252     }
1253 
1254     HILOG_INFO("ReAdd recycled forms end");
1255     return ERR_OK;
1256 }
1257 
HandleDestroyInJsThread()1258 void FormRenderRecord::HandleDestroyInJsThread()
1259 {
1260     HILOG_INFO("FormRenderService is exiting, destroy some resources in js thread");
1261     MarkThreadAlive();
1262     {
1263         std::lock_guard<std::mutex> lock(formRequestsMutex_);
1264         formRequests_.clear();
1265     }
1266     std::lock_guard<std::mutex> lock(formRendererGroupMutex_);
1267     formRendererGroupMap_.clear();
1268 }
1269 
ReleaseHapFileHandle()1270 void FormRenderRecord::ReleaseHapFileHandle()
1271 {
1272     HILOG_INFO("ReleaseHapFileHandle:%{public}s", hapPath_.c_str());
1273     if (hapPath_.empty()) {
1274         return;
1275     }
1276 
1277     std::string loadFilePath = AbilityBase::ExtractorUtil::GetLoadFilePath(hapPath_);
1278     AbilityBase::ExtractorUtil::DeleteExtractor(loadFilePath);
1279 }
1280 
GenerateContextKey(const FormJsInfo & formJsInfo)1281 inline std::string FormRenderRecord::GenerateContextKey(const FormJsInfo &formJsInfo)
1282 {
1283     return formJsInfo.bundleName + ":" +  formJsInfo.moduleName;
1284 }
1285 
ReloadFormRecord(const std::vector<FormJsInfo> && formJsInfos,const Want & want)1286 int32_t FormRenderRecord::ReloadFormRecord(const std::vector<FormJsInfo> &&formJsInfos, const Want &want)
1287 {
1288     HILOG_INFO("Reload form record");
1289     std::shared_ptr<EventHandler> eventHandler = GetEventHandler();
1290     if (eventHandler == nullptr) {
1291         if (!CheckEventHandler(true, true)) {
1292             HILOG_ERROR("null eventHandler");
1293             return ERR_APPEXECFWK_FORM_EVENT_HANDLER_NULL;
1294         }
1295 
1296         return ReAddRecycledForms(formJsInfos);
1297     }
1298 
1299     if (ReAddIfHapPathChanged(formJsInfos)) {
1300         return ERR_OK;
1301     }
1302 
1303     std::weak_ptr<FormRenderRecord> thisWeakPtr(shared_from_this());
1304     auto task = [thisWeakPtr, ids = std::forward<decltype(formJsInfos)>(formJsInfos), want]() {
1305         HILOG_DEBUG("HandleReloadFormRecord begin");
1306         auto renderRecord = thisWeakPtr.lock();
1307         if (renderRecord == nullptr) {
1308             HILOG_ERROR("null renderRecord");
1309             return;
1310         }
1311         renderRecord->HandleReloadFormRecord(std::move(ids), want);
1312     };
1313     eventHandler->PostTask(task, "ReloadFormRecord");
1314     return ReAddRecycledForms(formJsInfos);
1315 }
1316 
ReAddIfHapPathChanged(const std::vector<FormJsInfo> & formJsInfos)1317 bool FormRenderRecord::ReAddIfHapPathChanged(const std::vector<FormJsInfo> &formJsInfos)
1318 {
1319     std::shared_ptr<EventHandler> eventHandler = GetEventHandler();
1320     if (eventHandler == nullptr) {
1321         HILOG_ERROR("null eventHandler");
1322         return false;
1323     }
1324     HILOG_INFO("restart runtime");
1325     auto task = [weak = weak_from_this()]() {
1326         auto renderRecord = weak.lock();
1327         if (renderRecord == nullptr) {
1328             HILOG_ERROR("null renderRecord");
1329             return;
1330         }
1331         FormMemoryGuard memoryGuard;
1332         renderRecord->HandleReleaseAllRendererInJsThread();
1333     };
1334     SetEventHandlerNeedResetFlag(true);
1335     eventHandler->PostSyncTask(task, "ReleaseAllRenderer");
1336     Release();
1337     UpdateAllFormRequest(formJsInfos, true);
1338     SetEventHandlerNeedResetFlag(false);
1339     {
1340         std::lock_guard<std::recursive_mutex> lock(eventHandlerMutex_);
1341         CreateEventHandler(bundleName_, true);
1342     }
1343     return ReAddRecycledForms(formJsInfos) == ERR_OK;
1344 }
1345 
HandleReleaseAllRendererInJsThread()1346 void FormRenderRecord::HandleReleaseAllRendererInJsThread()
1347 {
1348     std::lock_guard<std::mutex> lock(formRendererGroupMutex_);
1349     MarkThreadAlive();
1350     for (const auto& iter : formRendererGroupMap_) {
1351         if (!iter.second) {
1352             HILOG_ERROR("null rendererGroup");
1353             continue;
1354         }
1355         int64_t formId = iter.first;
1356         HILOG_INFO("Release renderer which formId:%{public}" PRId64, formId);
1357         std::pair<std::vector<std::string>, std::string> compIds = iter.second->GetOrderedAndCurrentCompIds();
1358         iter.second->DeleteForm();
1359         DeleteRecycledFormCompIds(formId);
1360         InsertRecycledFormCompIds(formId, compIds);
1361     }
1362     formRendererGroupMap_.clear();
1363 }
1364 
UpdateAllFormRequest(const std::vector<FormJsInfo> & formJsInfos,bool hasRelease)1365 void FormRenderRecord::UpdateAllFormRequest(const std::vector<FormJsInfo> &formJsInfos, bool hasRelease)
1366 {
1367     std::lock_guard<std::mutex> lock(formRequestsMutex_);
1368     for (const auto &formJsInfo : formJsInfos) {
1369         auto iter = formRequests_.find(formJsInfo.formId);
1370         if (iter == formRequests_.end()) {
1371             HILOG_ERROR("%{public}" PRId64 " doesn't has formRequest", formJsInfo.formId);
1372             continue;
1373         }
1374         for (auto& formRequestIter : iter->second) {
1375             auto& formRequest = formRequestIter.second;
1376             formRequest.isDynamic = formJsInfo.isDynamic;
1377             formRequest.formJsInfo = formJsInfo;
1378             formRequest.hasRelease = hasRelease;
1379         }
1380     }
1381 }
1382 
OnUnlock()1383 int32_t FormRenderRecord::OnUnlock()
1384 {
1385     HILOG_DEBUG("call");
1386     std::weak_ptr<FormRenderRecord> thisWeakPtr(shared_from_this());
1387     auto task = [thisWeakPtr]() {
1388         HILOG_DEBUG("HandleOnUnlock begin");
1389         auto renderRecord = thisWeakPtr.lock();
1390         if (renderRecord == nullptr) {
1391             HILOG_ERROR("null renderRecord");
1392             return;
1393         }
1394         renderRecord->HandleOnUnlock();
1395     };
1396     std::shared_ptr<EventHandler> eventHandler = GetEventHandler();
1397     if (eventHandler == nullptr) {
1398         HILOG_ERROR("null eventHandler_");
1399         return RENDER_FORM_FAILED;
1400     }
1401     eventHandler->PostTask(task, "OnUnlock");
1402     return ERR_OK;
1403 }
1404 
HandleOnUnlock()1405 int32_t FormRenderRecord::HandleOnUnlock()
1406 {
1407     HILOG_INFO("call");
1408     {
1409         std::lock_guard<std::mutex> lock(formRequestsMutex_);
1410         for (auto& formRequests : formRequests_) {
1411             for (auto& formRequestElement : formRequests.second) {
1412                 formRequestElement.second.want.SetParam(Constants::FORM_RENDER_STATE, true);
1413             }
1414         }
1415     }
1416     std::lock_guard<std::mutex> lock(formRendererGroupMutex_);
1417     for (const auto& iter : formRendererGroupMap_) {
1418         if (iter.second) {
1419             iter.second->OnUnlock();
1420         }
1421     }
1422     return ERR_OK;
1423 }
1424 
SetVisibleChange(const int64_t & formId,bool isVisible)1425 int32_t FormRenderRecord::SetVisibleChange(const int64_t &formId, bool isVisible)
1426 {
1427     HILOG_INFO("SetVisibleChange, formId:%{public}s", std::to_string(formId).c_str());
1428     RecordFormVisibility(formId, isVisible);
1429     std::shared_ptr<EventHandler> eventHandler = GetEventHandler();
1430     if (eventHandler == nullptr) {
1431         HILOG_ERROR("null eventHandler");
1432         return SET_VISIBLE_CHANGE_FAILED;
1433     }
1434     auto task = [thisWeakPtr = weak_from_this(), formId, isVisible]() {
1435         auto renderRecord = thisWeakPtr.lock();
1436         if (renderRecord == nullptr) {
1437             HILOG_ERROR("null renderRecord");
1438             return;
1439         }
1440 
1441         renderRecord->HandleSetVisibleChange(formId, isVisible);
1442     };
1443 
1444     eventHandler->PostTask(task, "SetVisibleChange");
1445     return ERR_OK;
1446 }
1447 
HandleSetVisibleChange(const int64_t & formId,bool isVisible)1448 int32_t FormRenderRecord::HandleSetVisibleChange(const int64_t &formId, bool isVisible)
1449 {
1450     HILOG_INFO("HandleSetVisibleChange begin,formId:%{public}s", std::to_string(formId).c_str());
1451     MarkThreadAlive();
1452 
1453     std::lock_guard<std::mutex> lock(formRendererGroupMutex_);
1454     auto search = formRendererGroupMap_.find(formId);
1455     if (search == formRendererGroupMap_.end()) {
1456         HILOG_ERROR("invalid FormRendererGroup");
1457         return SET_VISIBLE_CHANGE_FAILED;
1458     }
1459     if (!search->second) {
1460         HILOG_ERROR("FormRendererGroup was founded but null");
1461         return SET_VISIBLE_CHANGE_FAILED;
1462     }
1463     search->second->SetVisibleChange(isVisible);
1464     return ERR_OK;
1465 }
1466 
HandleReloadFormRecord(const std::vector<FormJsInfo> && formJsInfos,const Want & want)1467 int32_t FormRenderRecord::HandleReloadFormRecord(const std::vector<FormJsInfo> &&formJsInfos, const Want &want)
1468 {
1469     HILOG_INFO("Reload record in js thread");
1470     MarkThreadAlive();
1471     if (runtime_ == nullptr) {
1472         HILOG_ERROR("null runtime_");
1473         return RELOAD_FORM_FAILED;
1474     }
1475     if (runtime_->GetLanguage() == AbilityRuntime::Runtime::Language::JS) {
1476         // In the card upgrade condition, new components may be added and need to be reloaded
1477         HILOG_DEBUG("ReloadFormComponent");
1478         (static_cast<AbilityRuntime::JsRuntime&>(*runtime_)).ReloadFormComponent();
1479     }
1480     std::lock_guard<std::mutex> lock(formRendererGroupMutex_);
1481     for (auto form : formJsInfos) {
1482         auto search = formRendererGroupMap_.find(form.formId);
1483         if (search == formRendererGroupMap_.end()) {
1484             HILOG_ERROR("invalid FormRendererGroup");
1485             continue;
1486         }
1487         auto group = search->second;
1488         if (!group) {
1489             HILOG_ERROR("null FormRendererGroup");
1490             continue;
1491         }
1492         group->ReloadForm(form);
1493     }
1494     return ERR_OK;
1495 }
1496 
FormCount()1497 size_t FormRenderRecord::FormCount()
1498 {
1499     return formRequests_.size();
1500 }
1501 
UpdateConfiguration(const std::shared_ptr<OHOS::AppExecFwk::Configuration> & config,const sptr<IFormSupply> & formSupplyClient)1502 void FormRenderRecord::UpdateConfiguration(
1503     const std::shared_ptr<OHOS::AppExecFwk::Configuration>& config, const sptr<IFormSupply> &formSupplyClient)
1504 {
1505     HILOG_INFO("UpdateConfiguration begin");
1506     if (!config) {
1507         HILOG_ERROR("UpdateConfiguration failed due to null config");
1508         return;
1509     }
1510 
1511     SetConfiguration(config);
1512     std::lock_guard<std::recursive_mutex> lock(eventHandlerMutex_);
1513     if (eventHandler_ == nullptr) {
1514         if (!CheckEventHandler(true, true)) {
1515             HILOG_ERROR("null eventHandler");
1516             return;
1517         }
1518 
1519         ReAddAllRecycledForms(formSupplyClient);
1520         return;
1521     }
1522 
1523     std::weak_ptr<FormRenderRecord> thisWeakPtr(shared_from_this());
1524     auto task = [thisWeakPtr, config]() {
1525         auto renderRecord = thisWeakPtr.lock();
1526         if (renderRecord == nullptr) {
1527             HILOG_ERROR("null renderRecord");
1528             return;
1529         }
1530         renderRecord->HandleUpdateConfiguration(config);
1531     };
1532 
1533     eventHandler_->PostTask(task, "UpdateConfiguration");
1534     ReAddAllRecycledForms(formSupplyClient);
1535 }
1536 
HandleUpdateConfiguration(const std::shared_ptr<OHOS::AppExecFwk::Configuration> & config)1537 void FormRenderRecord::HandleUpdateConfiguration(
1538     const std::shared_ptr<OHOS::AppExecFwk::Configuration>& config)
1539 {
1540     HILOG_INFO("HandleUpdateConfiguration begin");
1541     MarkThreadAlive();
1542     std::lock_guard<std::mutex> lock(formRendererGroupMutex_);
1543     if (!config) {
1544         HILOG_ERROR("null configuration");
1545         return;
1546     }
1547 
1548     for (auto iter = formRendererGroupMap_.begin(); iter != formRendererGroupMap_.end(); ++iter) {
1549         if (iter->second) {
1550             iter->second->UpdateConfiguration(config);
1551         }
1552     }
1553 }
1554 
FormRenderGC()1555 void FormRenderRecord::FormRenderGC()
1556 {
1557     std::weak_ptr<FormRenderRecord> thisWeakPtr(shared_from_this());
1558     auto task = [thisWeakPtr]() {
1559         auto renderRecord = thisWeakPtr.lock();
1560         if (renderRecord == nullptr) {
1561             HILOG_ERROR("null renderRecord");
1562             return;
1563         }
1564         renderRecord->HandleFormRenderGC();
1565     };
1566     if (eventHandler_ == nullptr) {
1567         HILOG_ERROR("null eventHandler_");
1568         return;
1569     }
1570     eventHandler_->PostSyncTask(task, "HandleFormRenderGC");
1571 }
1572 
HandleFormRenderGC()1573 void FormRenderRecord::HandleFormRenderGC()
1574 {
1575     HILOG_INFO("HandleFormRenderGC");
1576     if (runtime_ == nullptr) {
1577         HILOG_ERROR("null runtime_");
1578         return;
1579     }
1580     panda::JSNApi::HintGC((static_cast<AbilityRuntime::JsRuntime&>(*runtime_)).GetEcmaVm(),
1581         panda::JSNApi::MemoryReduceDegree::MIDDLE, panda::ecmascript::GCReason::EXTERNAL_TRIGGER);
1582 }
1583 
RecycleForm(const int64_t & formId,std::string & statusData)1584 int32_t FormRenderRecord::RecycleForm(const int64_t &formId, std::string &statusData)
1585 {
1586     HILOG_INFO("RecycleForm begin, formId:%{public}s", std::to_string(formId).c_str());
1587     int32_t result = RECYCLE_FORM_FAILED;
1588     if (!CheckEventHandler(true, true)) {
1589         HILOG_ERROR("null eventHandler_");
1590         return RENDER_FORM_FAILED;
1591     }
1592 
1593     auto task = [thisWeakPtr = weak_from_this(), formId, &statusData, &result]() {
1594         auto renderRecord = thisWeakPtr.lock();
1595         if (renderRecord == nullptr) {
1596             HILOG_ERROR("null renderRecord");
1597             return;
1598         }
1599 
1600         result = renderRecord->HandleRecycleForm(formId, statusData);
1601     };
1602     eventHandler_->PostSyncTask(task, "RecycleForm");
1603     return result;
1604 }
1605 
HandleRecycleForm(const int64_t & formId,std::string & statusData)1606 int32_t FormRenderRecord::HandleRecycleForm(const int64_t &formId, std::string &statusData)
1607 {
1608     HILOG_INFO("HandleRecycleForm begin,formId:%{public}s", std::to_string(formId).c_str());
1609     MarkThreadAlive();
1610 
1611     std::lock_guard<std::mutex> lock(formRendererGroupMutex_);
1612     auto search = formRendererGroupMap_.find(formId);
1613     if (search == formRendererGroupMap_.end()) {
1614         HILOG_ERROR("invalid FormRendererGroup");
1615         return RECYCLE_FORM_FAILED;
1616     }
1617     if (!search->second) {
1618         HILOG_ERROR("FormRendererGroup was founded but null");
1619         return RECYCLE_FORM_FAILED;
1620     }
1621 
1622     search->second->RecycleForm(statusData);
1623     return ERR_OK;
1624 }
1625 
RecoverForm(const FormJsInfo & formJsInfo,const std::string & statusData,const bool & isRecoverFormToHandleClickEvent)1626 int32_t FormRenderRecord::RecoverForm(const FormJsInfo &formJsInfo,
1627     const std::string &statusData, const bool &isRecoverFormToHandleClickEvent)
1628 {
1629     auto formId = formJsInfo.formId;
1630     HILOG_INFO("RecoverForm begin, formId:%{public}s", std::to_string(formId).c_str());
1631     if (!CheckEventHandler(true, true)) {
1632         HILOG_ERROR("null eventHandler_");
1633         return RENDER_FORM_FAILED;
1634     }
1635     std::shared_ptr<EventHandler> eventHandler = GetEventHandler();
1636 
1637     sptr<IFormSupply> formSupplyClient = GetFormSupplyClient();
1638     if (formSupplyClient == nullptr) {
1639         HILOG_ERROR("null formSupplyClient");
1640         return RENDER_FORM_FAILED;
1641     }
1642 
1643     std::weak_ptr<FormRenderRecord> thisWeakPtr(shared_from_this());
1644     auto task = [thisWeakPtr, formJsInfo, statusData, isRecoverFormToHandleClickEvent, formSupplyClient]() {
1645         auto renderRecord = thisWeakPtr.lock();
1646         if (renderRecord == nullptr) {
1647             HILOG_ERROR("renderRecord");
1648             return;
1649         }
1650         renderRecord->HandleRecoverForm(formJsInfo, statusData, isRecoverFormToHandleClickEvent);
1651         FormRenderStatusTaskMgr::GetInstance().OnRecoverFormDone(formJsInfo.formId,
1652             FormFsmEvent::RECOVER_FORM_DONE, formSupplyClient);
1653     };
1654     if (eventHandler == nullptr) {
1655         HILOG_ERROR("null eventHandler_ ");
1656         return RENDER_FORM_FAILED;
1657     }
1658     eventHandler->PostTask(task, "RecoverForm");
1659     return ERR_OK;
1660 }
1661 
HandleRecoverForm(const FormJsInfo & formJsInfo,const std::string & statusData,const bool & isHandleClickEvent)1662 void FormRenderRecord::HandleRecoverForm(const FormJsInfo &formJsInfo,
1663     const std::string &statusData, const bool &isHandleClickEvent)
1664 {
1665     auto formId = formJsInfo.formId;
1666     HILOG_INFO("HandleRecoverForm begin, formId:%{public}s, uid:%{public}s", std::to_string(formId).c_str(),
1667         uid_.c_str());
1668     std::unordered_map<std::string, Ace::FormRequest> formRequests;
1669     if (!GetFormRequestByFormId(formId, formRequests)) {
1670         HILOG_ERROR("not find formRequests");
1671         return;
1672     }
1673     if (formRequests.empty()) {
1674         HILOG_ERROR("empty formRequests");
1675         return;
1676     }
1677 
1678     if (!BeforeHandleUpdateForm(formRequests.begin()->second.formJsInfo)) {
1679         HILOG_ERROR("recover form prepare failed");
1680         return;
1681     }
1682 
1683     RecoverFormRequestsInGroup(formJsInfo, statusData, isHandleClickEvent, formRequests);
1684 }
1685 
GetAndDeleteRecycledCompIds(const int64_t & formId,std::vector<std::string> & orderedCompIds,std::string & currentCompId)1686 bool FormRenderRecord::GetAndDeleteRecycledCompIds(const int64_t &formId,
1687     std::vector<std::string> &orderedCompIds, std::string &currentCompId)
1688 {
1689     std::lock_guard<std::mutex> lock(recycledFormCompIdsMutex_);
1690     auto pairIter = recycledFormCompIds_.find(formId);
1691     if (pairIter == recycledFormCompIds_.end()) {
1692         HILOG_ERROR("invalid compIdPair,formId:%{public}" PRId64, formId);
1693         return false;
1694     }
1695     orderedCompIds = pairIter->second.first;
1696     currentCompId = pairIter->second.second;
1697     recycledFormCompIds_.erase(formId);
1698     HILOG_INFO("compIds size:%{public}zu,currentCompId:%{public}s,formId:%{public}" PRId64,
1699         orderedCompIds.size(), currentCompId.c_str(), formId);
1700     return true;
1701 }
1702 
RecoverFormRequestsInGroup(const FormJsInfo & formJsInfo,const std::string & statusData,const bool & isHandleClickEvent,std::unordered_map<std::string,Ace::FormRequest> & recordFormRequests)1703 bool FormRenderRecord::RecoverFormRequestsInGroup(const FormJsInfo &formJsInfo, const std::string &statusData,
1704     const bool &isHandleClickEvent, std::unordered_map<std::string, Ace::FormRequest> &recordFormRequests)
1705 {
1706     auto formId = formJsInfo.formId;
1707     std::vector<std::string> orderedCompIds;
1708     std::string currentCompId;
1709     bool flag = GetAndDeleteRecycledCompIds(formId, orderedCompIds, currentCompId);
1710     if (!flag) {
1711         HILOG_ERROR("init compIds failed,formId:%{public}" PRId64, formId);
1712         return false;
1713     }
1714 
1715     std::vector<Ace::FormRequest> groupRequests;
1716     size_t currentRequestIndex = 0;
1717     bool currentRequestFound = false;
1718     if (!GetFormRequestByFormId(formId, recordFormRequests)) {
1719         HILOG_ERROR("find formRequest failed,formId:%{public}" PRId64, formId);
1720         return false;
1721     }
1722 
1723     UpdateGroupRequestsWhenRecover(formId, formJsInfo, orderedCompIds, currentCompId, statusData, isHandleClickEvent,
1724         currentRequestIndex, groupRequests, currentRequestFound, recordFormRequests);
1725 
1726     if (groupRequests.empty()) {
1727         HILOG_ERROR("group requests empty formId:%{public}" PRId64, formId);
1728         return false;
1729     }
1730 
1731     if (!currentRequestFound) {
1732         // maybe current comp deleted between recover, get last comp as new current comp to recover
1733         currentRequestIndex = groupRequests.size() - 1;
1734         HILOG_WARN("current request index:%{public}zu formId:%{public}" PRId64, currentRequestIndex, formId);
1735     }
1736     bool success = RecoverRenderer(groupRequests, currentRequestIndex);
1737     if (success) {
1738         UpdateFormRequestReleaseState(formId, currentCompId, false);
1739     }
1740     return success;
1741 }
1742 
UpdateGroupRequestsWhenRecover(const int64_t & formId,const FormJsInfo & formJsInfo,const std::vector<std::string> & orderedCompIds,const std::string & currentCompId,const std::string & statusData,const bool & isHandleClickEvent,size_t & currentRequestIndex,std::vector<Ace::FormRequest> & groupRequests,bool & currentRequestFound,const std::unordered_map<std::string,Ace::FormRequest> & recordFormRequests)1743 void FormRenderRecord::UpdateGroupRequestsWhenRecover(const int64_t &formId, const FormJsInfo &formJsInfo,
1744     const std::vector<std::string> &orderedCompIds, const std::string &currentCompId, const std::string &statusData,
1745     const bool &isHandleClickEvent, size_t &currentRequestIndex, std::vector<Ace::FormRequest> &groupRequests,
1746     bool &currentRequestFound, const std::unordered_map<std::string, Ace::FormRequest> &recordFormRequests)
1747 {
1748     std::set<std::string> groupCompIds;
1749     for (auto compId : orderedCompIds) {
1750         auto recordRequestIter = recordFormRequests.find(compId);
1751         if (recordRequestIter == recordFormRequests.end()) {
1752             HILOG_WARN("invalid formRequest,formId:%{public}" PRId64 " compId=%{public}s", formId, compId.c_str());
1753             continue;
1754         }
1755         if (groupCompIds.find(compId) != groupCompIds.end()) {
1756             continue;
1757         }
1758         groupCompIds.insert(compId);
1759         auto& recordRequest = recordRequestIter->second;
1760         Ace::FormRequest groupRequest;
1761         groupRequest.compId = compId;
1762         groupRequest.want = recordRequest.want;
1763         groupRequest.formJsInfo = recordRequest.formJsInfo; // get json data from record request
1764         MergeMap(groupRequest.formJsInfo.imageDataMap, formJsInfo.imageDataMap);
1765         if (compId == currentCompId) {
1766             groupRequest.want.SetParam(Constants::FORM_STATUS_DATA, statusData);
1767             groupRequest.want.SetParam(Constants::FORM_IS_RECOVER_FORM_TO_HANDLE_CLICK_EVENT, isHandleClickEvent);
1768             currentRequestIndex = groupRequests.size();
1769             currentRequestFound = true;
1770             HILOG_INFO("currentRequestIndex: %{public}zu, formData.size: %{public}zu",
1771                 currentRequestIndex, groupRequest.formJsInfo.formData.size());
1772         }
1773         groupRequests.emplace_back(groupRequest);
1774     }
1775 }
1776 
MergeMap(std::map<std::string,sptr<FormAshmem>> & dst,const std::map<std::string,sptr<FormAshmem>> & src)1777 void FormRenderRecord::MergeMap(std::map<std::string, sptr<FormAshmem>> &dst,
1778     const std::map<std::string, sptr<FormAshmem>> &src)
1779 {
1780     for (auto iter = src.begin(); iter != src.end(); ++iter) {
1781         auto search = dst.find(iter->first);
1782         if (search == dst.end()) {
1783             dst.emplace(*iter);
1784         } else {
1785             search->second = iter->second;
1786         }
1787     }
1788 }
1789 
RecoverRenderer(const std::vector<Ace::FormRequest> & groupRequests,const size_t & currentRequestIndex)1790 bool FormRenderRecord::RecoverRenderer(const std::vector<Ace::FormRequest> &groupRequests,
1791     const size_t &currentRequestIndex)
1792 {
1793     if (currentRequestIndex >= groupRequests.size()) {
1794         HILOG_ERROR("current comp index %{public}zu invalid", currentRequestIndex);
1795         return false;
1796     }
1797     auto currentRequest = groupRequests[currentRequestIndex];
1798     auto context = GetContext(currentRequest.formJsInfo, currentRequest.want);
1799     if (context == nullptr) {
1800         HILOG_ERROR("Create Context failed");
1801         return false;
1802     }
1803 
1804     auto formRendererGroup = GetFormRendererGroup(currentRequest.formJsInfo, context, runtime_);
1805     if (formRendererGroup == nullptr) {
1806         HILOG_ERROR("Create formRendererGroup failed");
1807         return false;
1808     }
1809     auto task = [formRendererGroup, groupRequests, currentRequestIndex]() {
1810         HILOG_INFO("execute recover form task");
1811         formRendererGroup->RecoverRenderer(groupRequests, currentRequestIndex);
1812     };
1813     // the formrenderer_ must be initialized using a sync task
1814     eventHandler_->PostSyncTask(task, "RecoverRenderer");
1815     HILOG_INFO("recover renderer, formId:%{public}" PRId64, currentRequest.formJsInfo.formId);
1816     return true;
1817 }
1818 
UpdateFormSizeOfGroups(const int64_t & formId,float width,float height,float borderWidth)1819 void FormRenderRecord::UpdateFormSizeOfGroups(const int64_t &formId, float width, float height, float borderWidth)
1820 {
1821     {
1822         std::lock_guard<std::mutex> lock(formRequestsMutex_);
1823         auto iter = formRequests_.find(formId);
1824         if (iter == formRequests_.end()) {
1825             HILOG_ERROR("%{public}s doesn't has formRequest", std::to_string(formId).c_str());
1826             return;
1827         }
1828         if (iter->second.empty()) {
1829             HILOG_ERROR("empty formRequests");
1830             return;
1831         }
1832 
1833         HILOG_INFO("formRequests length: %{public}zu formId: %{public}" PRId64 " width: %{public}f height: %{public}f"
1834             " borderWidth: %{public}f", iter->second.size(), formId, width, height, borderWidth);
1835         for (auto& formRequestIter : iter->second) {
1836             formRequestIter.second.want.SetParam(
1837                 OHOS::AppExecFwk::Constants::PARAM_FORM_WIDTH_KEY, static_cast<double>(width));
1838             formRequestIter.second.want.SetParam(
1839                 OHOS::AppExecFwk::Constants::PARAM_FORM_HEIGHT_KEY, static_cast<double>(height));
1840             formRequestIter.second.want.SetParam(
1841                 OHOS::AppExecFwk::Constants::PARAM_FORM_BORDER_WIDTH_KEY, static_cast<float>(borderWidth));
1842         }
1843     }
1844 
1845     std::lock_guard<std::mutex> lock(formRendererGroupMutex_);
1846     auto search = formRendererGroupMap_.find(formId);
1847     if (search != formRendererGroupMap_.end()) {
1848         auto group = search->second;
1849         group->UpdateFormSizeOfFormRequests(width, height, borderWidth);
1850     }
1851 }
1852 
CheckManagerDelegateValid(const FormJsInfo & formJsInfo,const Want & want)1853 bool FormRenderRecord::CheckManagerDelegateValid(const FormJsInfo &formJsInfo, const Want &want)
1854 {
1855     HILOG_DEBUG("call");
1856     if (!want.HasParameter(FORM_RENDERER_PROCESS_ON_ADD_SURFACE)) {
1857         HILOG_INFO("not add surface, ingore it");
1858         return true;
1859     }
1860 
1861     auto context = GetContext(formJsInfo, want);
1862     if (context == nullptr) {
1863         return true;
1864     }
1865 
1866     {
1867         std::shared_lock<std::shared_mutex> lock(eventHandlerReset_);
1868         if (eventHandleNeedReset) {
1869             return true;
1870         }
1871     }
1872     std::lock_guard<std::mutex> lock(formRendererGroupMutex_);
1873     auto key = formJsInfo.formId;
1874     auto iter = formRendererGroupMap_.find(key);
1875     if (iter == formRendererGroupMap_.end() || iter->second == nullptr) {
1876         return true;
1877     }
1878 
1879     return iter->second->IsManagerDelegateValid(want);
1880 }
1881 
SetFormSupplyClient(const sptr<IFormSupply> & formSupplyClient)1882 void FormRenderRecord::SetFormSupplyClient(const sptr<IFormSupply> &formSupplyClient)
1883 {
1884     std::lock_guard<std::mutex> lock(formSupplyMutex_);
1885     formSupplyClient_ = formSupplyClient;
1886 }
1887 
GetFormSupplyClient()1888 sptr<IFormSupply> FormRenderRecord::GetFormSupplyClient()
1889 {
1890     std::lock_guard<std::mutex> lock(formSupplyMutex_);
1891     return formSupplyClient_;
1892 }
1893 
GetEventHandler()1894 std::shared_ptr<EventHandler> FormRenderRecord::GetEventHandler()
1895 {
1896     std::lock_guard<std::recursive_mutex> lock(eventHandlerMutex_);
1897     return eventHandler_;
1898 }
1899 
AddHostByFormId(int64_t formId,const sptr<IRemoteObject> hostRemoteObj)1900 int32_t FormRenderRecord::AddHostByFormId(int64_t formId, const sptr<IRemoteObject> hostRemoteObj)
1901 {
1902     std::lock_guard<std::mutex> lock(hostsMapMutex_);
1903     auto iter = hostsMapForFormId_.find(formId);
1904     if (iter == hostsMapForFormId_.end()) {
1905         hostsMapForFormId_.emplace(formId, IRemoteObjectSet({hostRemoteObj}));
1906         return ERR_OK;
1907     }
1908     iter->second.emplace(hostRemoteObj);
1909     return ERR_OK;
1910 }
1911 
DeleteHostRemoteObjByFormId(int64_t formId,const sptr<IRemoteObject> hostRemoteObj)1912 void FormRenderRecord::DeleteHostRemoteObjByFormId(int64_t formId, const sptr<IRemoteObject> hostRemoteObj)
1913 {
1914     std::lock_guard<std::mutex> lock(hostsMapMutex_);
1915     auto iter = hostsMapForFormId_.find(formId);
1916     if (iter != hostsMapForFormId_.end()) {
1917         std::unordered_set<sptr<IRemoteObject>, RemoteObjHash> &hosts = iter->second;
1918         hosts.erase(hostRemoteObj);
1919     }
1920 }
1921 
RemoveHostByFormId(int64_t formId)1922 void FormRenderRecord::RemoveHostByFormId(int64_t formId)
1923 {
1924     std::lock_guard<std::mutex> lock(hostsMapMutex_);
1925     hostsMapForFormId_.erase(formId);
1926 }
1927 
IsFormContextExist(const FormJsInfo & formJsInfo)1928 bool FormRenderRecord::IsFormContextExist(const FormJsInfo &formJsInfo)
1929 {
1930     std::lock_guard<std::mutex> lock(contextsMapMutex_);
1931     auto moduleInfo = contextsMapForModuleName_.find(GenerateContextKey(formJsInfo));
1932     return moduleInfo != contextsMapForModuleName_.end();
1933 }
1934 
GetFormRequestByFormId(int64_t formId,std::unordered_map<std::string,Ace::FormRequest> & formRequests)1935 bool FormRenderRecord::GetFormRequestByFormId(
1936     int64_t formId, std::unordered_map<std::string, Ace::FormRequest> &formRequests)
1937 {
1938     std::lock_guard<std::mutex> lock(formRequestsMutex_);
1939     auto iter = formRequests_.find(formId);
1940     if (iter == formRequests_.end()) {
1941         HILOG_WARN("not find form request,formId:%{public}" PRId64, formId);
1942         return false;
1943     }
1944 
1945     formRequests = iter->second;
1946     return true;
1947 }
1948 
SetEventHandlerNeedResetFlag(bool needReset)1949 void FormRenderRecord::SetEventHandlerNeedResetFlag(bool needReset)
1950 {
1951     std::lock_guard<std::shared_mutex> lock(eventHandlerReset_);
1952     HILOG_INFO("eventHandleNeedReset: %{public}d", needReset);
1953     eventHandleNeedReset = needReset;
1954 }
1955 
GetEventHandlerNeedReset()1956 bool FormRenderRecord::GetEventHandlerNeedReset()
1957 {
1958     std::lock_guard<std::shared_mutex> lock(eventHandlerReset_);
1959     HILOG_INFO("eventHandleNeedReset: %{public}d", eventHandleNeedReset);
1960     return eventHandleNeedReset;
1961 }
1962 
DeleteRecycledFormCompIds(int64_t formId)1963 void FormRenderRecord::DeleteRecycledFormCompIds(int64_t formId)
1964 {
1965     std::lock_guard<std::mutex> lock(recycledFormCompIdsMutex_);
1966     recycledFormCompIds_.erase(formId);
1967 }
1968 
InsertRecycledFormCompIds(int64_t formId,const std::pair<std::vector<std::string>,std::string> & compIds)1969 void FormRenderRecord::InsertRecycledFormCompIds(
1970     int64_t formId, const std::pair<std::vector<std::string>, std::string> &compIds)
1971 {
1972     std::lock_guard<std::mutex> lock(recycledFormCompIdsMutex_);
1973     recycledFormCompIds_.emplace(formId, compIds);
1974 }
1975 
RegisterUncatchableErrorHandler()1976 void FormRenderRecord::RegisterUncatchableErrorHandler()
1977 {
1978     auto nativeEnginePtr = (static_cast<AbilityRuntime::JsRuntime &>(*runtime_)).GetNativeEnginePointer();
1979     if (nativeEnginePtr == nullptr) {
1980         HILOG_ERROR("null nativeEnginePtr");
1981         return;
1982     }
1983     auto uncatchableTask = [weak = weak_from_this()](panda::TryCatch &trycatch) {
1984         auto renderRecord = weak.lock();
1985         if (renderRecord == nullptr) {
1986             HILOG_ERROR("null renderRecord");
1987             return;
1988         }
1989         auto exception = trycatch.GetAndClearException();
1990         if (!exception.IsEmpty() && !exception->IsHole()) {
1991             napi_value obj = reinterpret_cast<napi_value>(*exception);
1992             renderRecord->OnJsError(obj);
1993         }
1994     };
1995     panda::JSNApi::RegisterUncatchableErrorHandler(const_cast<EcmaVM *>(nativeEnginePtr->GetEcmaVm()), uncatchableTask);
1996 }
1997 
OnJsError(napi_value value)1998 void FormRenderRecord::OnJsError(napi_value value)
1999 {
2000     HILOG_ERROR("call, bundleName:  %{public}s", bundleName_.c_str());
2001     std::string errorName = GetNativeStrFromJsTaggedObj(value, "name");
2002     std::string errorMsg = GetNativeStrFromJsTaggedObj(value, "message");
2003     std::string stack = GetNativeStrFromJsTaggedObj(value, "stack");
2004     std::string errorCode = GetNativeStrFromJsTaggedObj(value, "code");
2005     std::string summary = "Error name:" + errorName + "\n" + "Error message:" + errorMsg + "\n";
2006     if (!errorCode.empty()) {
2007         summary += "Error code:" + errorCode + "\n";
2008     }
2009     HILOG_ERROR("summary: %{public}s", summary.c_str());
2010     HILOG_ERROR("stack: %{public}s", stack.c_str());
2011     FormRenderEventReport::SendBlockFaultEvent(bundleName_, summary, stack);
2012 }
2013 
GetNativeStrFromJsTaggedObj(napi_value obj,const char * key)2014 std::string FormRenderRecord::GetNativeStrFromJsTaggedObj(napi_value obj, const char* key)
2015 {
2016     if (obj == nullptr) {
2017         HILOG_ERROR("get value failed");
2018         return "";
2019     }
2020 
2021     napi_value valueStr = nullptr;
2022     napi_env env = (static_cast<AbilityRuntime::JsRuntime &>(*runtime_)).GetNapiEnv();
2023     bool hasProperty = false;
2024     napi_has_named_property(env, obj, key, &hasProperty);
2025     if (!hasProperty) {
2026         return "";
2027     }
2028     napi_get_named_property(env, obj, key, &valueStr);
2029     napi_valuetype valueType = napi_undefined;
2030     napi_typeof(env, valueStr, &valueType);
2031     if (valueType != napi_string) {
2032         HILOG_ERROR("convert value failed");
2033         return "";
2034     }
2035 
2036     size_t valueStrBufLength = 0;
2037     napi_get_value_string_utf8(env, valueStr, nullptr, 0, &valueStrBufLength);
2038     auto valueCStr = std::make_unique<char[]>(valueStrBufLength + 1);
2039     size_t valueStrLength = 0;
2040     napi_get_value_string_utf8(env, valueStr, valueCStr.get(), valueStrBufLength + 1, &valueStrLength);
2041     std::string ret(valueCStr.get(), valueStrLength);
2042     return ret;
2043 }
2044 
IsAllFormsInvisible()2045 bool FormRenderRecord::IsAllFormsInvisible()
2046 {
2047     std::lock_guard<std::mutex> lock(visibilityMapMutex_);
2048     return visibilityMap_.empty();
2049 }
2050 
RecordFormVisibility(int64_t formId,bool isVisible)2051 void FormRenderRecord::RecordFormVisibility(int64_t formId, bool isVisible)
2052 {
2053     HILOG_INFO("call formId: %{public}" PRId64 ", isVisible: %{public}d", formId, isVisible);
2054     std::lock_guard<std::mutex> lock(visibilityMapMutex_);
2055     if (isVisible) {
2056         visibilityMap_[formId] = isVisible;
2057     } else {
2058         visibilityMap_.erase(formId);
2059     }
2060 }
2061 
RecordFormLocation(int64_t formId,const FormLocationInfo & formLocation)2062 void FormRenderRecord::RecordFormLocation(int64_t formId, const FormLocationInfo &formLocation)
2063 {
2064     std::lock_guard<std::mutex> lock(formLocationMutex_);
2065     formLocationMap_[formId] = formLocation;
2066 }
2067 
DeleteFormLocation(int64_t formId)2068 void FormRenderRecord::DeleteFormLocation(int64_t formId)
2069 {
2070     std::lock_guard<std::mutex> lock(formLocationMutex_);
2071     formLocationMap_.erase(formId);
2072 }
2073 
ParseFormLocationMap(std::vector<std::string> & formName,std::vector<uint32_t> & formLocation)2074 void FormRenderRecord::ParseFormLocationMap(std::vector<std::string> &formName, std::vector<uint32_t> &formLocation)
2075 {
2076     std::lock_guard<std::mutex> lock(formLocationMutex_);
2077     for (const auto &iter : formLocationMap_) {
2078         const FormLocationInfo &locationInfo = iter.second;
2079         formName.emplace_back(locationInfo.formName);
2080         formLocation.emplace_back(locationInfo.formLocation);
2081     }
2082 }
2083 
RuntimeMemoryMonitor()2084 void FormRenderRecord::RuntimeMemoryMonitor()
2085 {
2086     if (runtime_ == nullptr || eventHandler_ == nullptr) {
2087         return;
2088     }
2089 
2090     auto nativeEnginePtr = (static_cast<AbilityRuntime::JsRuntime &>(*runtime_)).GetNativeEnginePointer();
2091     if (nativeEnginePtr == nullptr) {
2092         HILOG_ERROR("null nativeEnginePtr");
2093         return;
2094     }
2095 
2096     size_t totalSize = 0;
2097     size_t usedSize = 0;
2098     size_t objSize = 0;
2099     size_t limitSize = 0;
2100     // GetHeap must be called on the UI thread.
2101     auto task = [nativeEnginePtr, &totalSize, &usedSize, &objSize, &limitSize]() {
2102         totalSize = nativeEnginePtr->GetHeapTotalSize();
2103         usedSize = nativeEnginePtr->GetHeapUsedSize();
2104         objSize = nativeEnginePtr->GetHeapObjectSize();
2105         limitSize = nativeEnginePtr->GetHeapLimitSize();
2106     };
2107     eventHandler_->PostSyncTask(task, "RuntimeMemoryMonitorTask");
2108 
2109     uint64_t processMemory = GetPss();
2110     HILOG_INFO("processMemory: %{public}" PRIu64 ", bundleName: %{public}s, totalSize: %{public}zu, "
2111         "usedSize: %{public}zu, objSize: %{public}zu, limitSize: %{public}zu", processMemory, bundleName_.c_str(),
2112         totalSize, usedSize, objSize, limitSize);
2113     if (totalSize > RUNTIME_MEMORY_LIMIT) {
2114         std::vector<std::string> formName;
2115         std::vector<uint32_t> formLocation;
2116         ParseFormLocationMap(formName, formLocation);
2117         FormRenderEventReport::SendRuntimeMemoryLeakEvent(bundleName_, processMemory,
2118             static_cast<uint64_t>(totalSize), formName, formLocation);
2119     }
2120 }
2121 } // namespace FormRender
2122 } // namespace AppExecFwk
2123 } // namespace OHOS