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