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