• 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 <utility>
20 
21 #include "extractor.h"
22 #include "fms_log_wrapper.h"
23 #include "form_constants.h"
24 #include "form_module_checker.h"
25 #include "form_render_impl.h"
26 #include "xcollie/watchdog.h"
27 
28 namespace OHOS {
29 namespace AppExecFwk {
30 namespace FormRender {
31 constexpr int32_t RENDER_FORM_FAILED = -1;
32 constexpr int32_t RELOAD_FORM_FAILED = -1;
33 constexpr int32_t TIMEOUT = 3 * 1000;
34 constexpr int32_t CHECK_THREAD_TIME = 3;
35 constexpr char FORM_RENDERER_COMP_ID[] = "ohos.extra.param.key.form_comp_id";
36 
37 namespace {
GetCurrentTickMillseconds()38 uint64_t GetCurrentTickMillseconds()
39 {
40     return std::chrono::duration_cast<std::chrono::milliseconds>(
41         std::chrono::steady_clock::now().time_since_epoch()).count();
42 }
43 }
44 
ThreadState(int32_t maxState)45 ThreadState::ThreadState(int32_t maxState) : maxState_(maxState) {}
46 
ResetState()47 void ThreadState::ResetState()
48 {
49     state_ = 0;
50 }
51 
NextState()52 void ThreadState::NextState()
53 {
54     state_++;
55 }
56 
GetCurrentState()57 int32_t ThreadState::GetCurrentState()
58 {
59     return state_;
60 }
61 
IsMaxState()62 bool ThreadState::IsMaxState()
63 {
64     return state_ >= maxState_;
65 }
66 
Create(const std::string & bundleName,const std::string & uid,bool needMonitored)67 std::shared_ptr<FormRenderRecord> FormRenderRecord::Create(
68     const std::string &bundleName, const std::string &uid, bool needMonitored)
69 {
70     HILOG_INFO("%{public}s called.", __func__);
71     std::shared_ptr<FormRenderRecord> renderRecord = std::make_shared<FormRenderRecord>(bundleName, uid);
72     if (!renderRecord) {
73         HILOG_ERROR("Create FormRenderRecord failed.");
74         return nullptr;
75     }
76 
77     if (!renderRecord->CreateEventHandler(bundleName, needMonitored)) {
78         HILOG_ERROR("CreateEventHandler failed.");
79         return nullptr;
80     }
81     return renderRecord;
82 }
83 
FormRenderRecord(const std::string & bundleName,const std::string & uid)84 FormRenderRecord::FormRenderRecord(
85     const std::string &bundleName, const std::string &uid) : bundleName_(bundleName), uid_(uid)
86 {
87     threadState_ = std::make_shared<ThreadState>(CHECK_THREAD_TIME);
88 }
89 
~FormRenderRecord()90 FormRenderRecord::~FormRenderRecord()
91 {
92     std::shared_ptr<EventHandler> eventHandler = nullptr;
93     {
94         std::lock_guard<std::mutex> lock(eventHandlerMutex_);
95         eventHandler = eventHandler_;
96     }
97 
98     if (eventHandler == nullptr) {
99         return;
100     }
101 
102     // Some resources need to be deleted in a JS thread
103     auto syncTask = [renderRecord = this]() {
104         if (renderRecord == nullptr) {
105             HILOG_ERROR("renderRecord is nullptr.");
106             return;
107         }
108         renderRecord->HandleDestroyInJsThread();
109     };
110     eventHandler->PostSyncTask(syncTask);
111 }
112 
HandleHostDied(const sptr<IRemoteObject> hostRemoteObj)113 bool FormRenderRecord::HandleHostDied(const sptr<IRemoteObject> hostRemoteObj)
114 {
115     HILOG_INFO("Form host is died, clean resources.");
116     std::lock_guard<std::mutex> lock(hostsMapMutex_);
117     for (auto iter = hostsMapForFormId_.begin(); iter != hostsMapForFormId_.end();) {
118         std::unordered_set<sptr<IRemoteObject>, RemoteObjHash> &hosts = iter->second;
119         hosts.erase(hostRemoteObj);
120         if (hosts.empty()) {
121             iter = hostsMapForFormId_.erase(iter);
122         } else {
123             ++iter;
124         }
125     }
126     return hostsMapForFormId_.empty();
127 }
128 
CreateEventHandler(const std::string & bundleName,bool needMonitored)129 bool FormRenderRecord::CreateEventHandler(const std::string &bundleName, bool needMonitored)
130 {
131     HILOG_INFO("%{public}s called.", __func__);
132     if (eventHandler_) {
133         HILOG_DEBUG("EventHandle is exist, no need to create a new one.");
134         return true;
135     }
136     // Create event runner
137     HILOG_INFO("Create eventHandle.");
138     if (eventRunner_ == nullptr) {
139         eventRunner_ = EventRunner::Create(bundleName);
140         if (eventRunner_ == nullptr) {
141             HILOG_ERROR("Create event runner Failed.");
142             return false;
143         }
144     }
145     // Create event handler
146     eventHandler_ = std::make_shared<EventHandler>(eventRunner_);
147     if (eventHandler_ == nullptr) {
148         HILOG_ERROR("Create event handler failed.");
149         return false;
150     }
151 
152     if (needMonitored && !hasMonitor_) {
153         hasMonitor_.store(true);
154         AddWatchDogThreadMonitor();
155     }
156 
157     return true;
158 }
159 
AddWatchDogThreadMonitor()160 void FormRenderRecord::AddWatchDogThreadMonitor()
161 {
162     std::weak_ptr<FormRenderRecord> thisWeakPtr(shared_from_this());
163     auto watchdogTask = [thisWeakPtr]() {
164         auto renderRecord = thisWeakPtr.lock();
165         if (renderRecord) {
166             renderRecord->Timer();
167         }
168     };
169 
170     std::string eventHandleName;
171     eventHandleName.append(bundleName_).append(std::to_string(GetCurrentTickMillseconds()));
172     OHOS::HiviewDFX::Watchdog::GetInstance().RunPeriodicalTask(eventHandleName, watchdogTask, TIMEOUT);
173 }
174 
Timer()175 void FormRenderRecord::Timer()
176 {
177     TaskState taskState = RunTask();
178     if (taskState == TaskState::BLOCK) {
179         HILOG_ERROR("FRS block happened when bundleName is %{public}s", bundleName_.c_str());
180         OHOS::DelayedSingleton<FormRenderImpl>::GetInstance()->OnRenderingBlock(bundleName_);
181     }
182 }
183 
RunTask()184 TaskState FormRenderRecord::RunTask()
185 {
186     std::unique_lock<std::mutex> lock(watchDogMutex_);
187     {
188         std::lock_guard<std::mutex> lock(eventHandlerMutex_);
189         if (eventHandler_ == nullptr) {
190             HILOG_DEBUG("eventHandler is null when bundleName is %{public}s", bundleName_.c_str());
191             return TaskState::NO_RUNNING;
192         }
193     }
194 
195     if (!threadIsAlive_) {
196         threadState_->NextState();
197         HILOG_INFO("FRS block happened with threadState is %{public}d when bundleName is %{public}s",
198             threadState_->GetCurrentState(), bundleName_.c_str());
199         return threadState_->IsMaxState() ? TaskState::BLOCK : TaskState::RUNNING;
200     }
201 
202     threadIsAlive_ = false;
203     std::weak_ptr<FormRenderRecord> thisWeakPtr(shared_from_this());
204     auto checkTask = [thisWeakPtr] () {
205         auto renderRecord = thisWeakPtr.lock();
206         if (renderRecord == nullptr) {
207             HILOG_ERROR("renderRecord is nullptr.");
208             return;
209         }
210 
211         renderRecord->MarkThreadAlive();
212     };
213 
214     {
215         std::lock_guard<std::mutex> lock(eventHandlerMutex_);
216         if (eventHandler_ == nullptr) {
217             return TaskState::NO_RUNNING;
218         }
219 
220         if (!eventHandler_->PostTask(checkTask, "Watchdog Task", 0, AppExecFwk::EventQueue::Priority::IMMEDIATE)) {
221             HILOG_ERROR("Watchdog checkTask postTask false.");
222         }
223     }
224 
225     return TaskState::RUNNING;
226 }
227 
MarkThreadAlive()228 void FormRenderRecord::MarkThreadAlive()
229 {
230     std::unique_lock<std::mutex> lock(watchDogMutex_);
231     threadIsAlive_ = true;
232     threadState_->ResetState();
233 }
234 
UpdateRenderRecord(const FormJsInfo & formJsInfo,const Want & want,const sptr<IRemoteObject> hostRemoteObj)235 int32_t FormRenderRecord::UpdateRenderRecord(const FormJsInfo &formJsInfo, const Want &want, const sptr<IRemoteObject> hostRemoteObj)
236 {
237     HILOG_INFO("Updated record.");
238     {
239         // Some resources need to be initialized in a JS thread
240         std::lock_guard<std::mutex> lock(eventHandlerMutex_);
241         if (!CheckEventHandler(true, formJsInfo.isDynamic)) {
242             HILOG_ERROR("eventHandler_ is nullptr");
243             return RENDER_FORM_FAILED;
244         }
245 
246         std::weak_ptr<FormRenderRecord> thisWeakPtr(shared_from_this());
247         auto task = [thisWeakPtr, formJsInfo, want]() {
248             HILOG_DEBUG("HandleUpdateInJsThread begin.");
249             auto renderRecord = thisWeakPtr.lock();
250             if (renderRecord == nullptr) {
251                 HILOG_ERROR("renderRecord is nullptr.");
252                 return;
253             }
254             renderRecord->HandleUpdateInJsThread(formJsInfo, want);
255         };
256         eventHandler_->PostTask(task);
257     }
258 
259     if (hostRemoteObj == nullptr) {
260         HILOG_ERROR("hostRemoteObj is nullptr");
261         return RENDER_FORM_FAILED;
262     }
263     std::lock_guard<std::mutex> lock(hostsMapMutex_);
264     auto iter = hostsMapForFormId_.find(formJsInfo.formId);
265     if (iter == hostsMapForFormId_.end()) {
266         hostsMapForFormId_.emplace(formJsInfo.formId, IRemoteObjectSet({ hostRemoteObj }));
267         return ERR_OK;
268     }
269     iter->second.emplace(hostRemoteObj);
270     return ERR_OK;
271 }
272 
DeleteRenderRecord(int64_t formId,const std::string & compId,const sptr<IRemoteObject> hostRemoteObj,bool & isRenderGroupEmpty)273 void FormRenderRecord::DeleteRenderRecord(int64_t formId, const std::string &compId, const sptr<IRemoteObject> hostRemoteObj, bool &isRenderGroupEmpty)
274 {
275     // Some resources need to be deleted in a JS thread
276     HILOG_INFO("Delete some resources formId: %{public}" PRId64 ", %{public}s", formId, compId.c_str());
277     std::shared_ptr<EventHandler> eventHandler = nullptr;
278     {
279         std::lock_guard<std::mutex> lock(eventHandlerMutex_);
280         eventHandler = eventHandler_;
281     }
282 
283     if (eventHandler == nullptr) {
284         HILOG_ERROR("eventHandler is nullptr");
285         return;
286     }
287 
288     auto task = [weak = weak_from_this(), formId, compId, &isRenderGroupEmpty]() {
289         auto renderRecord = weak.lock();
290         if (renderRecord == nullptr) {
291             HILOG_ERROR("renderRecord is nullptr.");
292             return;
293         }
294 
295         isRenderGroupEmpty = renderRecord->HandleDeleteInJsThread(formId, compId);
296         renderRecord->DeleteStaticFormRequest(formId, compId);
297     };
298 
299     if (hostRemoteObj != nullptr) {
300         std::lock_guard<std::mutex> lock(hostsMapMutex_);
301         auto iter = hostsMapForFormId_.find(formId);
302         if (iter != hostsMapForFormId_.end()) {
303             std::unordered_set<sptr<IRemoteObject>, RemoteObjHash> &hosts = iter->second;
304             hosts.erase(hostRemoteObj);
305         }
306     }
307     eventHandler_->PostSyncTask(task);
308 }
309 
IsEmpty()310 bool FormRenderRecord::IsEmpty()
311 {
312     bool rendererEmpty = false;
313     bool staticFormRequestsEmpty = false;
314     {
315         std::lock_guard<std::mutex> lock(formRendererGroupMutex_);
316         rendererEmpty = formRendererGroupMap_.empty();
317     }
318     {
319         std::lock_guard<std::mutex> lock(staticFormRequestsMutex_);
320         staticFormRequestsEmpty = staticFormRequests_.empty();
321     }
322 
323     return rendererEmpty && staticFormRequestsEmpty;
324 }
325 
GetUid() const326 std::string FormRenderRecord::GetUid() const
327 {
328     return uid_;
329 }
330 
CreateRuntime(const FormJsInfo & formJsInfo)331 bool FormRenderRecord::CreateRuntime(const FormJsInfo &formJsInfo)
332 {
333     if (runtime_) {
334         HILOG_DEBUG("runtime is exist, no need to create a new one.");
335         return true;
336     }
337 
338     HILOG_INFO("Create a new runtime.");
339     if (eventRunner_ == nullptr) {
340         HILOG_ERROR("eventRunner_ is nullptr");
341         return false;
342     }
343 
344     AbilityRuntime::Runtime::Options options;
345     options.bundleName = formJsInfo.bundleName;
346     options.codePath = Constants::LOCAL_CODE_PATH;
347     BundleInfo bundleInfo;
348     options.eventRunner = eventRunner_;
349     options.hapPath = formJsInfo.jsFormCodePath;
350     options.loadAce = true;
351     options.isBundle = true;
352     options.isUnique = true;
353     options.moduleCheckerDelegate = std::make_shared<FormModuleChecker>();
354     runtime_ = AbilityRuntime::Runtime::Create(options);
355     if (runtime_ == nullptr) {
356         HILOG_ERROR("Create runtime Failed!");
357         return false;
358     }
359     hapPath_ = formJsInfo.jsFormCodePath;
360     return true;
361 }
362 
SetConfiguration(const std::shared_ptr<OHOS::AppExecFwk::Configuration> & config)363 void FormRenderRecord::SetConfiguration(const std::shared_ptr<OHOS::AppExecFwk::Configuration>& config)
364 {
365     configuration_ = config;
366 }
367 
GetContext(const FormJsInfo & formJsInfo,const Want & want)368 std::shared_ptr<AbilityRuntime::Context> FormRenderRecord::GetContext(const FormJsInfo &formJsInfo, const Want &want)
369 {
370     {
371         std::lock_guard<std::mutex> lock(contextsMapMutex_);
372         auto iter = contextsMapForModuleName_.find(GenerateContextKey(formJsInfo));
373         if (iter != contextsMapForModuleName_.end()) {
374             HILOG_DEBUG("Find context.");
375             return iter->second;
376         }
377     }
378 
379     return CreateContext(formJsInfo, want);
380 }
381 
CreateContext(const FormJsInfo & formJsInfo,const Want & want)382 std::shared_ptr<AbilityRuntime::Context> FormRenderRecord::CreateContext(const FormJsInfo &formJsInfo, const Want &want)
383 {
384     HILOG_INFO("Create a new context.");
385     auto context = std::make_shared<AbilityRuntime::ContextImpl>();
386     if (context == nullptr) {
387         HILOG_ERROR("Create context failed!");
388         return nullptr;
389     }
390 
391     context->SetConfiguration(configuration_);
392     AppExecFwk::HapModuleInfo hapModuleInfo;
393     hapModuleInfo.name = formJsInfo.moduleName;
394     hapModuleInfo.hapPath = formJsInfo.jsFormCodePath;
395     hapModuleInfo.compileMode = static_cast<CompileMode>(want.GetIntParam(Constants::FORM_COMPILE_MODE_KEY,
396         static_cast<int32_t>(CompileMode::ES_MODULE)));
397     context->InitHapModuleInfo(hapModuleInfo);
398     auto applicationInfo = std::make_shared<AppExecFwk::ApplicationInfo>();
399     applicationInfo->bundleName = formJsInfo.bundleName;
400     applicationInfo->minCompatibleVersionCode = want.GetIntParam(Constants::FORM_COMPATIBLE_VERSION_CODE_KEY, 0);
401     context->SetApplicationInfo(applicationInfo);
402     HILOG_DEBUG("bundleName is %{public}s, moduleName is %{public}s",
403         formJsInfo.bundleName.c_str(), formJsInfo.moduleName.c_str());
404 
405     std::lock_guard<std::mutex> lock(contextsMapMutex_);
406     contextsMapForModuleName_.emplace(GenerateContextKey(formJsInfo), context);
407     return context;
408 }
409 
GetFormRendererGroup(const FormJsInfo & formJsInfo,const std::shared_ptr<AbilityRuntime::Context> & context,const std::shared_ptr<AbilityRuntime::Runtime> & runtime)410 std::shared_ptr<Ace::FormRendererGroup> FormRenderRecord::GetFormRendererGroup(const FormJsInfo &formJsInfo,
411     const std::shared_ptr<AbilityRuntime::Context> &context, const std::shared_ptr<AbilityRuntime::Runtime> &runtime)
412 {
413     HILOG_INFO("Get formRendererGroup.");
414     auto key = formJsInfo.formId;
415     auto iter = formRendererGroupMap_.find(key);
416     if (iter != formRendererGroupMap_.end()) {
417         return iter->second;
418     }
419 
420     auto formRendererGroup = CreateFormRendererGroupLock(formJsInfo, context, runtime);
421     if (formRendererGroup != nullptr) {
422         HILOG_INFO("formRendererGroupMap emplace formId:%{public}s", std::to_string(key).c_str());
423         formRendererGroupMap_.emplace(key, formRendererGroup);
424     }
425     return formRendererGroup;
426 }
427 
CreateFormRendererGroupLock(const FormJsInfo & formJsInfo,const std::shared_ptr<AbilityRuntime::Context> & context,const std::shared_ptr<AbilityRuntime::Runtime> & runtime)428 std::shared_ptr<Ace::FormRendererGroup> FormRenderRecord::CreateFormRendererGroupLock(const FormJsInfo &formJsInfo,
429     const std::shared_ptr<AbilityRuntime::Context> &context, const std::shared_ptr<AbilityRuntime::Runtime> &runtime)
430 {
431     HILOG_INFO("Create formRendererGroup.");
432     auto formRendererGroup = Ace::FormRendererGroup::Create(context, runtime);
433     if (formRendererGroup == nullptr) {
434         HILOG_ERROR("Create formRendererGroup failed");
435         return nullptr;
436     }
437     return formRendererGroup;
438 }
439 
HandleUpdateInJsThread(const FormJsInfo & formJsInfo,const Want & want)440 void FormRenderRecord::HandleUpdateInJsThread(const FormJsInfo &formJsInfo, const Want &want)
441 {
442     HILOG_INFO("Update record in js thread.");
443     bool ret = BeforeHandleUpdateForm(formJsInfo);
444     if (!ret) {
445         HILOG_ERROR("Handle Update Form prepare failed");
446         return;
447     }
448 
449     HandleUpdateForm(formJsInfo, want);
450 }
451 
BeforeHandleUpdateForm(const FormJsInfo & formJsInfo)452 bool FormRenderRecord::BeforeHandleUpdateForm(const FormJsInfo &formJsInfo)
453 {
454     MarkThreadAlive();
455     if (runtime_ == nullptr && !CreateRuntime(formJsInfo)) {
456         HILOG_ERROR("Create runtime failed.");
457         return false;
458     }
459 
460     return true;
461 }
462 
HandleUpdateForm(const FormJsInfo & formJsInfo,const Want & want)463 void FormRenderRecord::HandleUpdateForm(const FormJsInfo &formJsInfo, const Want &want)
464 {
465     if (formJsInfo.isDynamic) {
466         HandleUpdateDynamicForm(formJsInfo, want);
467     } else {
468         HandleUpdateStaticForm(formJsInfo, want);
469     }
470 }
471 
HandleUpdateDynamicForm(const FormJsInfo & formJsInfo,const Want & want)472 void FormRenderRecord::HandleUpdateDynamicForm(const FormJsInfo &formJsInfo, const Want &want)
473 {
474     auto renderType = want.GetIntParam(Constants::FORM_RENDER_TYPE_KEY, Constants::RENDER_FORM);
475     HILOG_INFO("renderType is %{public}d.", renderType);
476     if (renderType == Constants::RENDER_FORM) {
477         AddRenderer(formJsInfo, want);
478     } else {
479         UpdateRenderer(formJsInfo);
480     }
481 
482     auto compId = want.GetStringParam(FORM_RENDERER_COMP_ID);
483     DeleteStaticFormRequest(formJsInfo.formId, compId);
484 }
485 
HandleUpdateStaticForm(const FormJsInfo & formJsInfo,const Want & want)486 void FormRenderRecord::HandleUpdateStaticForm(const FormJsInfo &formJsInfo, const Want &want)
487 {
488     auto renderType = want.GetIntParam(Constants::FORM_RENDER_TYPE_KEY, Constants::RENDER_FORM);
489     HILOG_INFO("renderType is %{public}d.", renderType);
490     if (renderType == Constants::RENDER_FORM) {
491         AddRenderer(formJsInfo, want);
492         AddStaticFormRequest(formJsInfo, want);
493         return;
494     }
495 
496     std::unordered_map<std::string, Ace::FormRequest> staticFormRequests;
497     {
498         std::lock_guard<std::mutex> lock(staticFormRequestsMutex_);
499         auto iter = staticFormRequests_.find(formJsInfo.formId);
500         if (iter == staticFormRequests_.end()) {
501             return;
502         }
503 
504         staticFormRequests = iter->second;
505     }
506 
507     for (const auto& iter : staticFormRequests) {
508         auto formRequest = iter.second;
509         formRequest.formJsInfo = formJsInfo;
510         if (!formRequest.hasRelease) {
511             UpdateRenderer(formJsInfo);
512             AddStaticFormRequest(formJsInfo.formId, formRequest);
513             continue;
514         }
515 
516         if (staticFormRequests.size() == 1) {
517             AddRenderer(formJsInfo, formRequest.want);
518             formRequest.hasRelease = false;
519             AddStaticFormRequest(formJsInfo.formId, formRequest);
520         }
521     }
522 }
523 
AddRenderer(const FormJsInfo & formJsInfo,const Want & want)524 void FormRenderRecord::AddRenderer(const FormJsInfo &formJsInfo, const Want &want)
525 {
526     auto context = GetContext(formJsInfo, want);
527     if (context == nullptr) {
528         HILOG_ERROR("Create Context failed.");
529         return;
530     }
531 
532     std::lock_guard<std::mutex> lock(formRendererGroupMutex_);
533     auto formRendererGroup = GetFormRendererGroup(formJsInfo, context, runtime_);
534     if (formRendererGroup == nullptr) {
535         HILOG_ERROR("Create formRendererGroup failed.");
536         return;
537     }
538     formRendererGroup->AddForm(want, formJsInfo);
539     HILOG_INFO("AddForm formId:%{public}s", std::to_string(formJsInfo.formId).c_str());
540 }
541 
UpdateRenderer(const FormJsInfo & formJsInfo)542 void FormRenderRecord::UpdateRenderer(const FormJsInfo &formJsInfo)
543 {
544     std::lock_guard<std::mutex> lock(formRendererGroupMutex_);
545     if (auto search = formRendererGroupMap_.find(formJsInfo.formId);
546         search != formRendererGroupMap_.end()) {
547         auto group = search->second;
548         group->UpdateForm(formJsInfo);
549     }
550     HILOG_INFO("UpdateForm formId:%{public}s", std::to_string(formJsInfo.formId).c_str());
551 }
552 
HandleDeleteInJsThread(int64_t formId,const std::string & compId)553 bool FormRenderRecord::HandleDeleteInJsThread(int64_t formId, const std::string &compId)
554 {
555     HILOG_INFO("Delete some resources in js thread.");
556     MarkThreadAlive();
557     {
558         std::lock_guard<std::mutex> lock(formRendererGroupMutex_);
559         auto search = formRendererGroupMap_.find(formId);
560         if (search == formRendererGroupMap_.end()) {
561             HILOG_INFO("HandleDeleteInJsThread failed. FormRendererGroup was not founded.");
562             return false;
563         }
564         if (!search->second) {
565             HILOG_INFO("HandleDeleteInJsThread failed. FormRendererGroup was founded but is null.");
566             return false;
567         }
568         if (!compId.empty()) {
569             search->second->DeleteForm(compId);
570             HILOG_INFO("HandleDeleteInJsThread compid is %{public}s", compId.c_str());
571             return false;
572         }
573         search->second->DeleteForm();
574         formRendererGroupMap_.erase(formId);
575     }
576     std::lock_guard<std::mutex> lock(hostsMapMutex_);
577     hostsMapForFormId_.erase(formId);
578     return true;
579 }
580 
CheckEventHandler(bool createThead,bool needMonitored)581 bool FormRenderRecord::CheckEventHandler(bool createThead, bool needMonitored)
582 {
583     if (eventHandler_ == nullptr && createThead) {
584         CreateEventHandler(bundleName_, needMonitored);
585     }
586 
587     return eventHandler_ != nullptr;
588 }
589 
AddStaticFormRequest(const FormJsInfo & formJsInfo,const Want & want)590 void FormRenderRecord::AddStaticFormRequest(const FormJsInfo &formJsInfo, const Want &want)
591 {
592     auto compId = want.GetStringParam(FORM_RENDERER_COMP_ID);
593     HILOG_INFO("AddStaticFormRequest formId: %{public}s, compId: %{public}s.",
594         std::to_string(formJsInfo.formId).c_str(), compId.c_str());
595     if (compId.empty()) {
596         return;
597     }
598 
599     std::lock_guard<std::mutex> lock(staticFormRequestsMutex_);
600     Ace::FormRequest formRequest;
601     formRequest.compId = compId;
602     formRequest.want = want;
603     formRequest.want.SetParam(Constants::FORM_RENDER_TYPE_KEY, Constants::RENDER_FORM);
604     formRequest.isDynamic = formJsInfo.isDynamic;
605     formRequest.formJsInfo = formJsInfo;
606     auto iter = staticFormRequests_.find(formJsInfo.formId);
607     if (iter == staticFormRequests_.end()) {
608         std::unordered_map<std::string, Ace::FormRequest> formRequests;
609         formRequests.emplace(compId, formRequest);
610         staticFormRequests_.emplace(formJsInfo.formId, formRequests);
611         return;
612     }
613 
614     auto innerIter = iter->second.find(compId);
615     if (innerIter != iter->second.end()) {
616         iter->second.erase(innerIter);
617     }
618     iter->second.emplace(compId, formRequest);
619 }
620 
AddStaticFormRequest(int64_t formId,const Ace::FormRequest & formRequest)621 void FormRenderRecord::AddStaticFormRequest(int64_t formId, const Ace::FormRequest &formRequest)
622 {
623     HILOG_INFO("AddStaticFormRequest by FormRequest formId: %{public}s, compId: %{public}s.",
624         std::to_string(formId).c_str(), formRequest.compId.c_str());
625     std::lock_guard<std::mutex> lock(staticFormRequestsMutex_);
626     auto iter = staticFormRequests_.find(formId);
627     if (iter == staticFormRequests_.end()) {
628         std::unordered_map<std::string, Ace::FormRequest> formRequests;
629         formRequests.emplace(formRequest.compId, formRequest);
630         staticFormRequests_.emplace(formId, formRequests);
631         return;
632     }
633 
634     auto innerIter = iter->second.find(formRequest.compId);
635     if (innerIter != iter->second.end()) {
636         iter->second.erase(innerIter);
637     }
638     iter->second.emplace(formRequest.compId, formRequest);
639 }
640 
DeleteStaticFormRequest(int64_t formId,const std::string & compId)641 void FormRenderRecord::DeleteStaticFormRequest(int64_t formId, const std::string &compId)
642 {
643     HILOG_INFO("DeleteStaticFormRequest formId: %{public}s, compId: %{public}s.",
644         std::to_string(formId).c_str(), compId.c_str());
645     std::lock_guard<std::mutex> lock(staticFormRequestsMutex_);
646     auto iter = staticFormRequests_.find(formId);
647     if (iter == staticFormRequests_.end()) {
648         return;
649     }
650 
651     auto innerIter = iter->second.find(compId);
652     if (innerIter != iter->second.end()) {
653         iter->second.erase(innerIter);
654         if (iter->second.empty()) {
655             staticFormRequests_.erase(iter);
656         }
657     }
658 }
659 
UpdateStaticFormRequestReleaseState(int64_t formId,const std::string & compId,bool hasRelease)660 void FormRenderRecord::UpdateStaticFormRequestReleaseState(
661     int64_t formId, const std::string &compId, bool hasRelease)
662 {
663     HILOG_INFO("UpdateStatic ReleaseState formId: %{public}s, compId: %{public}s, hasRelease: %{public}d.",
664         std::to_string(formId).c_str(), compId.c_str(), hasRelease);
665     std::lock_guard<std::mutex> lock(staticFormRequestsMutex_);
666     auto iter = staticFormRequests_.find(formId);
667     if (iter == staticFormRequests_.end()) {
668         return;
669     }
670 
671     auto innerIter = iter->second.find(compId);
672     if (innerIter == iter->second.end()) {
673         return;
674     }
675 
676     if (innerIter->second.isDynamic) {
677         return;
678     }
679 
680     innerIter->second.hasRelease = hasRelease;
681 }
682 
ReleaseRenderer(int64_t formId,const std::string & compId,bool & isRenderGroupEmpty)683 void FormRenderRecord::ReleaseRenderer(
684     int64_t formId, const std::string &compId, bool &isRenderGroupEmpty)
685 {
686     HILOG_INFO("Release renderer which formId: %{public}s, compId: %{public}s start.",
687         std::to_string(formId).c_str(), compId.c_str());
688     std::shared_ptr<EventHandler> eventHandler = nullptr;
689     {
690         std::lock_guard<std::mutex> lock(eventHandlerMutex_);
691         eventHandler = eventHandler_;
692     }
693 
694     if (eventHandler == nullptr) {
695         HILOG_ERROR("eventHandler is nullptr");
696         return;
697     }
698 
699     auto task = [weak = weak_from_this(), formId, compId, &isRenderGroupEmpty]() {
700         auto renderRecord = weak.lock();
701         if (renderRecord == nullptr) {
702             HILOG_ERROR("renderRecord is nullptr.");
703             return;
704         }
705 
706         bool ret = renderRecord->HandleReleaseRendererInJsThread(formId, compId, isRenderGroupEmpty);
707         if (ret) {
708             renderRecord->UpdateStaticFormRequestReleaseState(formId, compId, true);
709         }
710     };
711     eventHandler->PostSyncTask(task);
712 }
713 
HandleReleaseRendererInJsThread(int64_t formId,const std::string & compId,bool & isRenderGroupEmpty)714 bool FormRenderRecord::HandleReleaseRendererInJsThread(
715     int64_t formId, const std::string &compId, bool &isRenderGroupEmpty)
716 {
717     HILOG_INFO("Release renderer which formId: %{public}s, compId: %{public}s in js thread.",
718         std::to_string(formId).c_str(), compId.c_str());
719     MarkThreadAlive();
720     if (compId.empty()) {
721         return false;
722     }
723 
724     std::lock_guard<std::mutex> lock(formRendererGroupMutex_);
725     auto search = formRendererGroupMap_.find(formId);
726     if (search == formRendererGroupMap_.end()) {
727         HILOG_INFO("HandleReleaseRenderer failed. FormRendererGroup was not founded.");
728         return false;
729     }
730 
731     if (!search->second) {
732         HILOG_INFO("HandleReleaseRenderer failed. FormRendererGroup was founded but is null.");
733         return false;
734     }
735 
736     search->second->DeleteForm(compId);
737     if (search->second->IsFormRequestsEmpty()) {
738         formRendererGroupMap_.erase(formId);
739     }
740 
741     isRenderGroupEmpty = formRendererGroupMap_.empty();
742     return true;
743 }
744 
Release()745 void FormRenderRecord::Release()
746 {
747     HILOG_INFO("Release runtime and eventHandler.");
748     std::lock_guard<std::mutex> lock(eventHandlerMutex_);
749     if (eventHandler_ == nullptr) {
750         HILOG_INFO("eventHandler is null.");
751         return;
752     }
753 
754     auto syncTask = [renderRecord = this]() {
755         if (renderRecord == nullptr) {
756             HILOG_ERROR("renderRecord is nullptr.");
757             return;
758         }
759         renderRecord->HandleReleaseInJsThread();
760     };
761     eventHandler_->PostSyncTask(syncTask, "HandleReleaseInJsThread");
762     if (eventRunner_) {
763         eventRunner_->Stop();
764         eventRunner_.reset();
765     }
766 
767     eventHandler_.reset();
768 }
769 
HandleReleaseInJsThread()770 void FormRenderRecord::HandleReleaseInJsThread()
771 {
772     if (runtime_) {
773         runtime_.reset();
774     }
775     ReleaseHapFileHandle();
776 }
777 
ReAddAllStaticForms()778 void FormRenderRecord::ReAddAllStaticForms()
779 {
780     HILOG_INFO("ReAdd all static forms start.");
781     if (!CheckEventHandler(false)) {
782         HILOG_ERROR("CheckEventHandler failed.");
783         return;
784     }
785 
786     std::lock_guard<std::mutex> lock(staticFormRequestsMutex_);
787     for (const auto& staticFormRequests : staticFormRequests_) {
788         for (const auto& staticFormRequest : staticFormRequests.second) {
789             if (staticFormRequest.second.isDynamic || !staticFormRequest.second.hasRelease) {
790                 continue;
791             }
792 
793             std::weak_ptr<FormRenderRecord> thisWeakPtr(shared_from_this());
794             auto task = [thisWeakPtr, formJsInfo = staticFormRequest.second.formJsInfo,
795                 want = staticFormRequest.second.want]() {
796                 auto renderRecord = thisWeakPtr.lock();
797                 if (renderRecord) {
798                     renderRecord->HandleUpdateInJsThread(formJsInfo, want);
799                 }
800             };
801             eventHandler_->PostTask(task);
802         }
803     }
804 
805     HILOG_INFO("ReAdd all static forms end.");
806 }
807 
ReAddStaticForms(const std::vector<FormJsInfo> & formJsInfos)808 void FormRenderRecord::ReAddStaticForms(const std::vector<FormJsInfo> &formJsInfos)
809 {
810     HILOG_INFO("ReAdd static form start");
811     if (!CheckEventHandler(false)) {
812         HILOG_ERROR("CheckEventHandler failed.");
813         return;
814     }
815 
816     std::lock_guard<std::mutex> lock(staticFormRequestsMutex_);
817     for (const auto &form : formJsInfos) {
818         auto iter = staticFormRequests_.find(form.formId);
819         if (iter == staticFormRequests_.end()) {
820             continue;
821         }
822 
823         for (const auto& staticFormRequest : iter->second) {
824             if (!staticFormRequest.second.hasRelease) {
825                 continue;
826             }
827 
828             std::weak_ptr<FormRenderRecord> thisWeakPtr(shared_from_this());
829             auto task = [thisWeakPtr, form,
830                     want = staticFormRequest.second.want]() {
831                 auto renderRecord = thisWeakPtr.lock();
832                 if (renderRecord) {
833                     renderRecord->HandleUpdateInJsThread(form, want);
834                 }
835             };
836             eventHandler_->PostTask(task);
837         }
838     }
839 
840     HILOG_INFO("ReAdd static form end.");
841 }
842 
HandleDestroyInJsThread()843 void FormRenderRecord::HandleDestroyInJsThread()
844 {
845     HILOG_INFO("FormRenderService is exiting, destroy some resources in js thread.");
846     MarkThreadAlive();
847     {
848         std::lock_guard<std::mutex> lock(staticFormRequestsMutex_);
849         staticFormRequests_.clear();
850     }
851     std::lock_guard<std::mutex> lock(formRendererGroupMutex_);
852     formRendererGroupMap_.clear();
853     runtime_.reset();
854     ReleaseHapFileHandle();
855 }
856 
ReleaseHapFileHandle()857 void FormRenderRecord::ReleaseHapFileHandle()
858 {
859     HILOG_INFO("ReleaseHapFileHandle: %{public}s", hapPath_.c_str());
860     if (hapPath_.empty()) {
861         return;
862     }
863 
864     std::string loadFilePath = AbilityBase::ExtractorUtil::GetLoadFilePath(hapPath_);
865     AbilityBase::ExtractorUtil::DeleteExtractor(loadFilePath);
866 }
867 
GenerateContextKey(const FormJsInfo & formJsInfo)868 inline std::string FormRenderRecord::GenerateContextKey(const FormJsInfo &formJsInfo)
869 {
870     return formJsInfo.bundleName + ":" +  formJsInfo.moduleName;
871 }
872 
ReloadFormRecord(const std::vector<FormJsInfo> && formJsInfos,const Want & want)873 int32_t FormRenderRecord::ReloadFormRecord(const std::vector<FormJsInfo> &&formJsInfos, const Want &want)
874 {
875     HILOG_INFO("Reload form record");
876     std::lock_guard<std::mutex> lock(eventHandlerMutex_);
877     if (eventHandler_ == nullptr) {
878         if (!CheckEventHandler(true, false)) {
879             HILOG_ERROR("eventHandler is nullptr");
880             return RELOAD_FORM_FAILED;
881         }
882 
883         ReAddStaticForms(formJsInfos);
884         return ERR_OK;
885     }
886 
887     std::weak_ptr<FormRenderRecord> thisWeakPtr(shared_from_this());
888     auto task = [thisWeakPtr, ids = std::forward<decltype(formJsInfos)>(formJsInfos), want]() {
889         HILOG_DEBUG("HandleReloadFormRecord begin.");
890         auto renderRecord = thisWeakPtr.lock();
891         if (renderRecord == nullptr) {
892             HILOG_ERROR("renderRecord is nullptr.");
893             return;
894         }
895         renderRecord->HandleReloadFormRecord(std::move(ids), want);
896     };
897     eventHandler_->PostTask(task);
898     ReAddStaticForms(formJsInfos);
899     return ERR_OK;
900 }
901 
OnUnlock()902 int32_t FormRenderRecord::OnUnlock()
903 {
904     HILOG_DEBUG("OnUnlock called");
905     std::weak_ptr<FormRenderRecord> thisWeakPtr(shared_from_this());
906     auto task = [thisWeakPtr]() {
907         HILOG_DEBUG("HandleOnUnlock begin.");
908         auto renderRecord = thisWeakPtr.lock();
909         if (renderRecord == nullptr) {
910             HILOG_ERROR("renderRecord is nullptr.");
911             return;
912         }
913         renderRecord->HandleOnUnlock();
914     };
915     if (eventHandler_ == nullptr) {
916         HILOG_ERROR("eventHandler_ is nullptr.");
917         return RENDER_FORM_FAILED;
918     }
919     eventHandler_->PostTask(task);
920     return ERR_OK;
921 }
922 
HandleOnUnlock()923 int32_t FormRenderRecord::HandleOnUnlock()
924 {
925     HILOG_INFO("HandleOnUnlock called.");
926     std::lock_guard<std::mutex> lock(formRendererGroupMutex_);
927     for (const auto& iter : formRendererGroupMap_) {
928         if (iter.second) {
929             iter.second->OnUnlock();
930         }
931     }
932     return ERR_OK;
933 }
934 
HandleReloadFormRecord(const std::vector<FormJsInfo> && formJsInfos,const Want & want)935 int32_t FormRenderRecord::HandleReloadFormRecord(const std::vector<FormJsInfo> &&formJsInfos, const Want &want)
936 {
937     HILOG_INFO("Reload record in js thread.");
938     MarkThreadAlive();
939     if (runtime_ == nullptr) {
940         HILOG_ERROR("runtime_ is null.");
941         return RELOAD_FORM_FAILED;
942     }
943     if (runtime_->GetLanguage() == AbilityRuntime::Runtime::Language::JS) {
944         // In the card upgrade condition, new components may be added and need to be reloaded
945         HILOG_DEBUG("ReloadFormComponent.");
946         (static_cast<AbilityRuntime::JsRuntime&>(*runtime_)).ReloadFormComponent();
947     }
948     std::lock_guard<std::mutex> lock(formRendererGroupMutex_);
949     for (auto form : formJsInfos) {
950         auto search = formRendererGroupMap_.find(form.formId);
951         if (search == formRendererGroupMap_.end()) {
952             HILOG_ERROR("HandleReloadFormRecord failed. FormRendererGroup was not found.");
953             continue;
954         }
955         auto group = search->second;
956         if (!group) {
957             HILOG_ERROR("HandleReloadFormRecord failed. FormRendererGroup is null.");
958             continue;
959         }
960         if (!form.isDynamic) {
961             for (auto formRequest : group->GetAllRendererFormRequests()) {
962                 formRequest.isDynamic = false;
963                 formRequest.formJsInfo = form;
964                 AddStaticFormRequest(form.formId, formRequest);
965             }
966         }
967         group->ReloadForm(form);
968     }
969     return ERR_OK;
970 }
971 
UpdateConfiguration(const std::shared_ptr<OHOS::AppExecFwk::Configuration> & config)972 void FormRenderRecord::UpdateConfiguration(
973     const std::shared_ptr<OHOS::AppExecFwk::Configuration>& config)
974 {
975     HILOG_INFO("UpdateConfiguration begin");
976     if (!config) {
977         HILOG_ERROR("UpdateConfiguration failed due to config is nullptr");
978         return;
979     }
980 
981     SetConfiguration(config);
982     std::lock_guard<std::mutex> lock(eventHandlerMutex_);
983     if (eventHandler_ == nullptr) {
984         if (!CheckEventHandler(true, false)) {
985             HILOG_ERROR("eventHandler is nullptr");
986             return;
987         }
988 
989         ReAddAllStaticForms();
990         return;
991     }
992 
993     std::weak_ptr<FormRenderRecord> thisWeakPtr(shared_from_this());
994     auto task = [thisWeakPtr, config]() {
995         auto renderRecord = thisWeakPtr.lock();
996         if (renderRecord == nullptr) {
997             HILOG_ERROR("renderRecord is nullptr.");
998             return;
999         }
1000         renderRecord->HandleUpdateConfiguration(config);
1001     };
1002 
1003     eventHandler_->PostTask(task);
1004     ReAddAllStaticForms();
1005 }
1006 
HandleUpdateConfiguration(const std::shared_ptr<OHOS::AppExecFwk::Configuration> & config)1007 void FormRenderRecord::HandleUpdateConfiguration(
1008     const std::shared_ptr<OHOS::AppExecFwk::Configuration>& config)
1009 {
1010     HILOG_INFO("HandleUpdateConfiguration begin.");
1011     MarkThreadAlive();
1012     std::lock_guard<std::mutex> lock(formRendererGroupMutex_);
1013     if (!config) {
1014         HILOG_ERROR("configuration is nullptr");
1015         return;
1016     }
1017 
1018     for (auto iter = formRendererGroupMap_.begin(); iter != formRendererGroupMap_.end(); ++iter) {
1019         if (iter->second) {
1020             iter->second->UpdateConfiguration(config);
1021         }
1022     }
1023 }
1024 } // namespace FormRender
1025 } // namespace AppExecFwk
1026 } // namespace OHOS
1027