• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "form_render_record.h"
17 
18 #include <utility>
19 
20 #include "form_constants.h"
21 #include "hilog_wrapper.h"
22 
23 namespace OHOS {
24 namespace AppExecFwk {
25 namespace FormRender {
26 constexpr int32_t RENDER_FORM_FAILED = -1;
27 constexpr int32_t RELOAD_FORM_FAILED = -1;
28 
Create(const std::string & bundleName,const std::string & uid)29 std::shared_ptr<FormRenderRecord> FormRenderRecord::Create(const std::string &bundleName, const std::string &uid)
30 {
31     HILOG_INFO("%{public}s called.", __func__);
32     std::shared_ptr<FormRenderRecord> renderRecord = std::make_shared<FormRenderRecord>(bundleName, uid);
33     if (!renderRecord) {
34         HILOG_ERROR("Create FormRenderRecord failed.");
35         return nullptr;
36     }
37 
38     if (!renderRecord->CreateEventHandler(bundleName)) {
39         HILOG_ERROR("CreateEventHandler failed.");
40         return nullptr;
41     }
42     return renderRecord;
43 }
44 
FormRenderRecord(const std::string & bundleName,const std::string & uid)45 FormRenderRecord::FormRenderRecord(
46     const std::string &bundleName, const std::string &uid) : bundleName_(bundleName), uid_(uid) {}
47 
~FormRenderRecord()48 FormRenderRecord::~FormRenderRecord()
49 {
50     // Some resources need to be deleted in a JS thread
51     auto syncTask = [renderRecord = this]() {
52         if (renderRecord == nullptr) {
53             HILOG_ERROR("renderRecord is nullptr.");
54             return;
55         }
56         renderRecord->HandleDestroyInJsThread();
57     };
58     eventHandler_->PostSyncTask(syncTask);
59 }
60 
HandleHostDied(const sptr<IRemoteObject> hostRemoteObj)61 bool FormRenderRecord::HandleHostDied(const sptr<IRemoteObject> hostRemoteObj)
62 {
63     HILOG_INFO("Form host is died, clean resources.");
64     std::lock_guard<std::mutex> lock(hostsMapMutex_);
65     for (auto iter = hostsMapForFormId_.begin(); iter != hostsMapForFormId_.end();) {
66         std::unordered_set<sptr<IRemoteObject>, RemoteObjHash> &hosts = iter->second;
67         hosts.erase(hostRemoteObj);
68         if (hosts.empty()) {
69             iter = hostsMapForFormId_.erase(iter);
70         } else {
71             ++iter;
72         }
73     }
74     return hostsMapForFormId_.empty();
75 }
76 
CreateEventHandler(const std::string & bundleName)77 bool FormRenderRecord::CreateEventHandler(const std::string &bundleName)
78 {
79     HILOG_INFO("%{public}s called.", __func__);
80     if (eventHandler_) {
81         HILOG_DEBUG("EventHandle is exist, no need to create a new one.");
82         return true;
83     }
84     // Create event runner
85     HILOG_INFO("Create eventHandle.");
86     if (eventRunner_ == nullptr) {
87         eventRunner_ = EventRunner::Create(bundleName);
88         if (eventRunner_ == nullptr) {
89             HILOG_ERROR("Create event runner Failed.");
90             return false;
91         }
92     }
93     // Create event handler
94     eventHandler_ = std::make_shared<EventHandler>(eventRunner_);
95     if (eventHandler_ == nullptr) {
96         HILOG_ERROR("Create event handler failed.");
97         return false;
98     }
99     return true;
100 }
101 
UpdateRenderRecord(const FormJsInfo & formJsInfo,const Want & want,const sptr<IRemoteObject> hostRemoteObj)102 int32_t FormRenderRecord::UpdateRenderRecord(const FormJsInfo &formJsInfo, const Want &want, const sptr<IRemoteObject> hostRemoteObj)
103 {
104     HILOG_INFO("Updated record.");
105 
106     // Some resources need to be initialized in a JS thread
107     std::weak_ptr<FormRenderRecord> thisWeakPtr(shared_from_this());
108     auto task = [thisWeakPtr, formJsInfo, want]() {
109         HILOG_DEBUG("HandleUpdateInJsThread begin.");
110         auto renderRecord = thisWeakPtr.lock();
111         if (renderRecord == nullptr) {
112             HILOG_ERROR("renderRecord is nullptr.");
113             return;
114         }
115         renderRecord->HandleUpdateInJsThread(formJsInfo, want);
116     };
117 
118     if (eventHandler_ == nullptr) {
119         HILOG_ERROR("eventHandler_ is nullptr");
120         return RENDER_FORM_FAILED;
121     }
122     eventHandler_->PostTask(task);
123 
124     if (hostRemoteObj == nullptr) {
125         HILOG_ERROR("hostRemoteObj is nullptr");
126         return RENDER_FORM_FAILED;
127     }
128     std::lock_guard<std::mutex> lock(hostsMapMutex_);
129     auto iter = hostsMapForFormId_.find(formJsInfo.formId);
130     if (iter == hostsMapForFormId_.end()) {
131         hostsMapForFormId_.emplace(formJsInfo.formId, IRemoteObjectSet({ hostRemoteObj }));
132         return ERR_OK;
133     }
134     iter->second.emplace(hostRemoteObj);
135     return ERR_OK;
136 }
137 
DeleteRenderRecord(int64_t formId,const std::string & compId,const sptr<IRemoteObject> hostRemoteObj,bool & isRenderGroupEmpty)138 void FormRenderRecord::DeleteRenderRecord(int64_t formId, const std::string &compId, const sptr<IRemoteObject> hostRemoteObj, bool &isRenderGroupEmpty)
139 {
140     // Some resources need to be deleted in a JS thread
141     HILOG_INFO("Delete some resources formId:%{public}s %{public}s", std::to_string(formId).c_str(), compId.c_str());
142     if (eventHandler_ == nullptr) {
143         HILOG_ERROR("eventHandler_ is nullptr");
144         return;
145     }
146 
147     auto task = [weak = weak_from_this(), formId, compId, &isRenderGroupEmpty]() {
148         auto renderRecord = weak.lock();
149         if (renderRecord == nullptr) {
150             HILOG_ERROR("renderRecord is nullptr.");
151             return;
152         }
153 
154         isRenderGroupEmpty = renderRecord->HandleDeleteInJsThread(formId, compId);
155     };
156 
157     if (hostRemoteObj != nullptr) {
158         std::lock_guard<std::mutex> lock(hostsMapMutex_);
159         auto iter = hostsMapForFormId_.find(formId);
160         if (iter != hostsMapForFormId_.end()) {
161             std::unordered_set<sptr<IRemoteObject>, RemoteObjHash> &hosts = iter->second;
162             hosts.erase(hostRemoteObj);
163         }
164     }
165     eventHandler_->PostSyncTask(task);
166 }
167 
IsEmpty()168 bool FormRenderRecord::IsEmpty()
169 {
170     std::lock_guard<std::mutex> lock(formRendererGroupMutex_);
171     return formRendererGroupMap_.empty();
172 }
173 
GetUid() const174 std::string FormRenderRecord::GetUid() const
175 {
176     return uid_;
177 }
178 
CreateRuntime(const FormJsInfo & formJsInfo)179 bool FormRenderRecord::CreateRuntime(const FormJsInfo &formJsInfo)
180 {
181     if (runtime_) {
182         HILOG_DEBUG("runtime is exist, no need to create a new one.");
183         return true;
184     }
185 
186     HILOG_INFO("Create a new runtime.");
187     if (eventRunner_ == nullptr) {
188         HILOG_ERROR("eventRunner_ is nullptr");
189         return false;
190     }
191     AbilityRuntime::Runtime::Options options;
192     options.bundleName = formJsInfo.bundleName;
193     options.codePath = Constants::LOCAL_CODE_PATH;
194     BundleInfo bundleInfo;
195     options.eventRunner = eventRunner_;
196     options.hapPath = formJsInfo.jsFormCodePath;
197     options.loadAce = true;
198     options.isBundle = true;
199     options.isUnique = true;
200     runtime_ = AbilityRuntime::Runtime::Create(options);
201     if (runtime_ == nullptr) {
202         HILOG_ERROR("Create runtime Failed!");
203         return false;
204     }
205     return true;
206 }
207 
GetContext(const FormJsInfo & formJsInfo,const Want & want)208 std::shared_ptr<AbilityRuntime::Context> FormRenderRecord::GetContext(const FormJsInfo &formJsInfo, const Want &want)
209 {
210     {
211         std::lock_guard<std::mutex> lock(contextsMapMutex_);
212         auto iter = contextsMapForModuleName_.find(GenerateContextKey(formJsInfo));
213         if (iter != contextsMapForModuleName_.end()) {
214             HILOG_DEBUG("Find context.");
215             return iter->second;
216         }
217     }
218 
219     return CreateContext(formJsInfo, want);
220 }
221 
CreateContext(const FormJsInfo & formJsInfo,const Want & want)222 std::shared_ptr<AbilityRuntime::Context> FormRenderRecord::CreateContext(const FormJsInfo &formJsInfo, const Want &want)
223 {
224     HILOG_INFO("Create a new context.");
225     auto context = std::make_shared<AbilityRuntime::ContextImpl>();
226     if (context == nullptr) {
227         HILOG_ERROR("Create context failed!");
228         return nullptr;
229     }
230 
231     context->SetConfiguration(configuration_);
232     AppExecFwk::HapModuleInfo hapModuleInfo;
233     hapModuleInfo.name = formJsInfo.moduleName;
234     hapModuleInfo.hapPath = formJsInfo.jsFormCodePath;
235     hapModuleInfo.compileMode = static_cast<CompileMode>(want.GetIntParam(Constants::FORM_COMPILE_MODE_KEY,
236         static_cast<int32_t>(CompileMode::ES_MODULE)));
237     context->InitHapModuleInfo(hapModuleInfo);
238     auto applicationInfo = std::make_shared<AppExecFwk::ApplicationInfo>();
239     applicationInfo->bundleName = formJsInfo.bundleName;
240     applicationInfo->minCompatibleVersionCode = want.GetIntParam(Constants::FORM_COMPATIBLE_VERSION_CODE_KEY, 0);
241     context->SetApplicationInfo(applicationInfo);
242     HILOG_DEBUG("bundleName is %{public}s, moduleName is %{public}s",
243         formJsInfo.bundleName.c_str(), formJsInfo.moduleName.c_str());
244 
245     std::lock_guard<std::mutex> lock(contextsMapMutex_);
246     contextsMapForModuleName_.emplace(GenerateContextKey(formJsInfo), context);
247     return context;
248 }
249 
SetConfiguration(const std::shared_ptr<OHOS::AppExecFwk::Configuration> & config)250 void FormRenderRecord::SetConfiguration(const std::shared_ptr<OHOS::AppExecFwk::Configuration>& config)
251 {
252     configuration_ = config;
253 }
254 
GetFormRendererGroup(const FormJsInfo & formJsInfo,const std::shared_ptr<AbilityRuntime::Context> & context,const std::shared_ptr<AbilityRuntime::Runtime> & runtime)255 std::shared_ptr<Ace::FormRendererGroup> FormRenderRecord::GetFormRendererGroup(const FormJsInfo &formJsInfo,
256     const std::shared_ptr<AbilityRuntime::Context> &context, const std::shared_ptr<AbilityRuntime::Runtime> &runtime)
257 {
258     HILOG_INFO("Get formRendererGroup.");
259     std::lock_guard<std::mutex> lock(formRendererGroupMutex_);
260     auto key = formJsInfo.formId;
261     auto iter = formRendererGroupMap_.find(key);
262     if (iter != formRendererGroupMap_.end()) {
263         return iter->second;
264     }
265 
266     auto formRendererGroup = CreateFormRendererGroupLock(formJsInfo, context, runtime);
267     if (formRendererGroup != nullptr) {
268         HILOG_INFO("formRendererGroupMap emplace formId:%{public}s", std::to_string(key).c_str());
269         formRendererGroupMap_.emplace(key, formRendererGroup);
270     }
271     return formRendererGroup;
272 }
273 
CreateFormRendererGroupLock(const FormJsInfo & formJsInfo,const std::shared_ptr<AbilityRuntime::Context> & context,const std::shared_ptr<AbilityRuntime::Runtime> & runtime)274 std::shared_ptr<Ace::FormRendererGroup> FormRenderRecord::CreateFormRendererGroupLock(const FormJsInfo &formJsInfo,
275     const std::shared_ptr<AbilityRuntime::Context> &context, const std::shared_ptr<AbilityRuntime::Runtime> &runtime)
276 {
277     HILOG_INFO("Create formRendererGroup.");
278     auto formRendererGroup = Ace::FormRendererGroup::Create(context, runtime);
279     if (formRendererGroup == nullptr) {
280         HILOG_ERROR("Create formRendererGroup failed");
281         return nullptr;
282     }
283     return formRendererGroup;
284 }
285 
HandleUpdateInJsThread(const FormJsInfo & formJsInfo,const Want & want)286 void FormRenderRecord::HandleUpdateInJsThread(const FormJsInfo &formJsInfo, const Want &want)
287 {
288     HILOG_INFO("Update record in js thread.");
289     if (runtime_ == nullptr && !CreateRuntime(formJsInfo)) {
290         HILOG_ERROR("Create runtime failed.");
291         return;
292     }
293     auto context = GetContext(formJsInfo, want);
294     if (context == nullptr) {
295         HILOG_ERROR("Create Context failed.");
296         return;
297     }
298     auto renderType = want.GetIntParam(Constants::FORM_RENDER_TYPE_KEY, Constants::RENDER_FORM);
299     HILOG_INFO("renderType is %{public}d.", renderType);
300     if (renderType == Constants::RENDER_FORM) {
301         auto formRendererGroup = GetFormRendererGroup(formJsInfo, context, runtime_);
302         if (formRendererGroup == nullptr) {
303             HILOG_ERROR("Create formRendererGroup failed.");
304             return;
305         }
306         formRendererGroup->AddForm(want, formJsInfo);
307         HILOG_INFO("AddForm formId:%{public}s", std::to_string(formJsInfo.formId).c_str());
308     } else {
309         std::lock_guard<std::mutex> lock(formRendererGroupMutex_);
310         if (auto search = formRendererGroupMap_.find(formJsInfo.formId);
311             search != formRendererGroupMap_.end()) {
312             auto group = search->second;
313             group->UpdateForm(formJsInfo);
314         }
315         HILOG_INFO("UpdateForm formId:%{public}s", std::to_string(formJsInfo.formId).c_str());
316     }
317     return;
318 }
319 
HandleDeleteInJsThread(int64_t formId,const std::string & compId)320 bool FormRenderRecord::HandleDeleteInJsThread(int64_t formId, const std::string &compId)
321 {
322     HILOG_INFO("Delete some resources in js thread.");
323     {
324         std::lock_guard<std::mutex> lock(formRendererGroupMutex_);
325         auto search = formRendererGroupMap_.find(formId);
326         if (search == formRendererGroupMap_.end()) {
327             HILOG_INFO("HandleDeleteInJsThread failed. FormRendererGroup was not founded.");
328             return false;
329         }
330         if (!search->second) {
331             HILOG_INFO("HandleDeleteInJsThread failed. FormRendererGroup was founded but is null.");
332             return false;
333         }
334         if (!compId.empty()) {
335             search->second->DeleteForm(compId);
336             HILOG_INFO("HandleDeleteInJsThread compid is %{public}s", compId.c_str());
337             return false;
338         }
339         search->second->DeleteForm();
340         formRendererGroupMap_.erase(formId);
341     }
342     std::lock_guard<std::mutex> lock(hostsMapMutex_);
343     hostsMapForFormId_.erase(formId);
344     return true;
345 }
346 
HandleDestroyInJsThread()347 void FormRenderRecord::HandleDestroyInJsThread()
348 {
349     HILOG_INFO("FormRenderService is exiting, destroy some resources in js thread.");
350     std::lock_guard<std::mutex> lock(formRendererGroupMutex_);
351     formRendererGroupMap_.clear();
352     runtime_.reset();
353 }
354 
GenerateContextKey(const FormJsInfo & formJsInfo)355 inline std::string FormRenderRecord::GenerateContextKey(const FormJsInfo &formJsInfo)
356 {
357     return formJsInfo.bundleName + ":" +  formJsInfo.moduleName;
358 }
359 
ReloadFormRecord(const std::vector<int64_t> && formIds,const Want & want)360 int32_t FormRenderRecord::ReloadFormRecord(const std::vector<int64_t> &&formIds, const Want &want)
361 {
362     HILOG_INFO("Reload form record");
363     std::weak_ptr<FormRenderRecord> thisWeakPtr(shared_from_this());
364     auto task = [thisWeakPtr, ids = std::forward<decltype(formIds)>(formIds), want]() {
365         HILOG_DEBUG("HandleReloadFormRecord begin.");
366         auto renderRecord = thisWeakPtr.lock();
367         if (renderRecord == nullptr) {
368             HILOG_ERROR("renderRecord is nullptr.");
369             return;
370         }
371         renderRecord->HandleReloadFormRecord(std::move(ids), want);
372     };
373     if (eventHandler_ == nullptr) {
374         HILOG_ERROR("eventHandler_ is nullptr");
375         return RELOAD_FORM_FAILED;
376     }
377     eventHandler_->PostTask(task);
378     return ERR_OK;
379 }
380 
HandleReloadFormRecord(const std::vector<int64_t> && formIds,const Want & want)381 int32_t FormRenderRecord::HandleReloadFormRecord(const std::vector<int64_t> &&formIds, const Want &want)
382 {
383     HILOG_INFO("Reload record in js thread.");
384     std::lock_guard<std::mutex> lock(formRendererGroupMutex_);
385     for (auto formId : formIds) {
386         auto search = formRendererGroupMap_.find(formId);
387         if (search == formRendererGroupMap_.end()) {
388             HILOG_ERROR("HandleReloadFormRecord failed. FormRendererGroup was not found.");
389             continue;
390         }
391         auto group = search->second;
392         if (!group) {
393             HILOG_ERROR("HandleReloadFormRecord failed. FormRendererGroup is null.");
394             continue;
395         }
396         group->ReloadForm();
397     }
398     return ERR_OK;
399 }
400 
UpdateConfiguration(const std::shared_ptr<OHOS::AppExecFwk::Configuration> & config)401 void FormRenderRecord::UpdateConfiguration(
402     const std::shared_ptr<OHOS::AppExecFwk::Configuration>& config)
403 {
404     HILOG_INFO("UpdateConfiguration begin");
405     if (!config) {
406         HILOG_ERROR("UpdateConfiguration failed due to config is nullptr");
407         return;
408     }
409 
410     std::weak_ptr<FormRenderRecord> thisWeakPtr(shared_from_this());
411     auto task = [thisWeakPtr, config]() {
412         auto renderRecord = thisWeakPtr.lock();
413         if (renderRecord == nullptr) {
414             HILOG_ERROR("renderRecord is nullptr.");
415             return;
416         }
417         renderRecord->HandleUpdateConfiguration(config);
418     };
419     if (eventHandler_ == nullptr) {
420         HILOG_ERROR("eventHandler_ is nullptr");
421         return;
422     }
423     eventHandler_->PostTask(task);
424 }
425 
HandleUpdateConfiguration(const std::shared_ptr<OHOS::AppExecFwk::Configuration> & config)426 void FormRenderRecord::HandleUpdateConfiguration(
427     const std::shared_ptr<OHOS::AppExecFwk::Configuration>& config)
428 {
429     HILOG_INFO("HandleUpdateConfiguration begin.");
430     std::lock_guard<std::mutex> lock(formRendererGroupMutex_);
431     for (auto iter = formRendererGroupMap_.begin(); iter != formRendererGroupMap_.end(); ++iter) {
432         if (iter->second) {
433             iter->second->UpdateConfiguration(config);
434         }
435     }
436 }
437 } // namespace FormRender
438 } // namespace AppExecFwk
439 } // namespace OHOS
440