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