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