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