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