• 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_impl.h"
17 
18 #include <cstddef>
19 #include <memory>
20 
21 #include "event_handler.h"
22 #include "fms_log_wrapper.h"
23 #include "form_constants.h"
24 #include "form_render_event_report.h"
25 #include "form_render_service_extension.h"
26 #include "js_runtime.h"
27 #include "service_extension.h"
28 #include "form_memmgr_client.h"
29 #ifdef SUPPORT_POWER
30 #include "power_mgr_client.h"
31 #endif
32 
33 namespace OHOS {
34 namespace AppExecFwk {
35 namespace FormRender {
36 namespace {
37 constexpr int32_t RENDER_FORM_FAILED = -1;
38 constexpr int32_t RELOAD_FORM_FAILED = -1;
39 constexpr int32_t RECYCLE_FORM_FAILED = -1;
40 constexpr int32_t SET_VISIBLE_CHANGE_FAILED = -1;
41 constexpr int32_t FORM_RENDER_TASK_DELAY_TIME = 20; // ms
42 constexpr int32_t ENABLE_FORM_FAILED = -1;
43 }
44 using namespace AbilityRuntime;
45 using namespace OHOS::AAFwk::GlobalConfigurationKey;
46 
FormRenderServiceCreator(const std::unique_ptr<Runtime> & runtime)47 static OHOS::AbilityRuntime::ServiceExtension *FormRenderServiceCreator(const std::unique_ptr<Runtime> &runtime)
48 {
49     HILOG_DEBUG("Create FormRenderServiceExtension");
50     return FormRenderServiceExtension::Create(runtime);
51 }
52 
RegisterServiceExtensionCreator()53 __attribute__((constructor)) void RegisterServiceExtensionCreator()
54 {
55     HILOG_DEBUG("Set FormRenderServiceExtension creator");
56     OHOS::AbilityRuntime::ServiceExtension::SetCreator(FormRenderServiceCreator);
57 }
58 
FormRenderImpl()59 FormRenderImpl::FormRenderImpl()
60 {
61     const std::string queueName = "FormRenderSerialQueue";
62     serialQueue_ = std::make_shared<FormRenderSerialQueue>(queueName);
63     if (serialQueue_ == nullptr) {
64         HILOG_ERROR("null serialQueue_");
65     }
66 }
67 
68 FormRenderImpl::~FormRenderImpl() = default;
69 
RenderForm(const FormJsInfo & formJsInfo,const Want & want,sptr<IRemoteObject> callerToken)70 int32_t FormRenderImpl::RenderForm(const FormJsInfo &formJsInfo, const Want &want,
71     sptr<IRemoteObject> callerToken)
72 {
73     HILOG_INFO("Render form,bundleName=%{public}s,abilityName=%{public}s,formName=%{public}s,"
74         "moduleName=%{public}s,jsFormCodePath=%{public}s,formSrc=%{public}s,formId=%{public}" PRId64,
75         formJsInfo.bundleName.c_str(), formJsInfo.abilityName.c_str(), formJsInfo.formName.c_str(),
76         formJsInfo.moduleName.c_str(), formJsInfo.jsFormCodePath.c_str(), formJsInfo.formSrc.c_str(),
77         formJsInfo.formId);
78 
79     sptr<IFormSupply> formSupplyClient = iface_cast<IFormSupply>(callerToken);
80     if (formSupplyClient == nullptr) {
81         HILOG_ERROR("null IFormSupply");
82         return ERR_APPEXECFWK_FORM_BIND_PROVIDER_FAILED;
83     }
84     {
85         std::lock_guard<std::mutex> lock(formSupplyMutex_);
86         formSupplyClient_ = formSupplyClient;
87     }
88     HILOG_DEBUG("connectId:%{public}d",
89         want.GetIntParam(Constants::FORM_CONNECT_ID, 0L));
90 
91     std::string uid = want.GetStringParam(Constants::FORM_SUPPLY_UID);
92     if (uid.empty()) {
93         HILOG_ERROR("GetUid failed");
94         return ERR_APPEXECFWK_FORM_BIND_PROVIDER_FAILED;
95     }
96     int32_t result = ERR_OK;
97     Want formRenderWant(want);
98     sptr<IRemoteObject> hostToken = formRenderWant.GetRemoteObject(Constants::PARAM_FORM_HOST_TOKEN);
99     {
100         std::lock_guard<std::mutex> lock(renderRecordMutex_);
101         ConfirmUnlockState(formRenderWant);
102         if (auto search = renderRecordMap_.find(uid); search != renderRecordMap_.end()) {
103             result = search->second->UpdateRenderRecord(formJsInfo, formRenderWant, hostToken);
104         } else {
105             auto record = FormRenderRecord::Create(formJsInfo.bundleName, uid, formJsInfo.isDynamic, formSupplyClient);
106             if (record == nullptr) {
107                 HILOG_ERROR("null record");
108                 return RENDER_FORM_FAILED;
109             }
110 
111             record->SetConfiguration(configuration_);
112             result = record->UpdateRenderRecord(formJsInfo, formRenderWant, hostToken);
113             if (renderRecordMap_.empty()) {
114                 FormMemmgrClient::GetInstance().SetCritical(true);
115             }
116             renderRecordMap_.emplace(uid, record);
117             FormRenderGCTask(uid);
118         }
119     }
120     formSupplyClient->OnRenderTaskDone(formJsInfo.formId, formRenderWant);
121     return result;
122 }
123 
StopRenderingForm(const FormJsInfo & formJsInfo,const Want & want,const sptr<IRemoteObject> & callerToken)124 int32_t FormRenderImpl::StopRenderingForm(const FormJsInfo &formJsInfo, const Want &want,
125     const sptr<IRemoteObject> &callerToken)
126 {
127     HILOG_INFO("call");
128     sptr<IFormSupply> formSupplyClient = iface_cast<IFormSupply>(callerToken);
129     if (formSupplyClient == nullptr) {
130         HILOG_ERROR("null IFormSupply");
131         return ERR_APPEXECFWK_FORM_BIND_PROVIDER_FAILED;
132     }
133 
134     std::string uid = want.GetStringParam(Constants::FORM_SUPPLY_UID);
135     if (uid.empty()) {
136         HILOG_ERROR("GetUid failed");
137         return ERR_APPEXECFWK_FORM_BIND_PROVIDER_FAILED;
138     }
139 
140     bool isRenderGroupEmpty = false;
141     sptr<IRemoteObject> hostToken = want.GetRemoteObject(Constants::PARAM_FORM_HOST_TOKEN);
142     {
143         std::lock_guard<std::mutex> lock(renderRecordMutex_);
144         auto search = renderRecordMap_.find(uid);
145         if (search == renderRecordMap_.end()) {
146             HILOG_ERROR("fail");
147             return RENDER_FORM_FAILED;
148         }
149 
150         if (!search->second) {
151             HILOG_ERROR("fail");
152             return RENDER_FORM_FAILED;
153         }
154 
155         std::string compId = want.GetStringParam(Constants::FORM_RENDER_COMP_ID);
156         search->second->DeleteRenderRecord(formJsInfo.formId, compId, hostToken, isRenderGroupEmpty);
157         if (search->second->IsEmpty()) {
158             renderRecordMap_.erase(search);
159             HILOG_INFO("DeleteRenderRecord success,uid:%{public}s", uid.c_str());
160             if (renderRecordMap_.empty()) {
161                 FormMemmgrClient::GetInstance().SetCritical(false);
162             }
163         }
164     }
165 
166     HILOG_INFO("connectId:%{public}d",
167         want.GetIntParam(Constants::FORM_CONNECT_ID, 0L));
168     if (isRenderGroupEmpty) {
169         formSupplyClient->OnStopRenderingTaskDone(formJsInfo.formId, want);
170     }
171 
172     return ERR_OK;
173 }
174 
ReleaseRenderer(int64_t formId,const std::string & compId,const std::string & uid)175 int32_t FormRenderImpl::ReleaseRenderer(int64_t formId, const std::string &compId, const std::string &uid)
176 {
177     HILOG_INFO("formId:%{public}" PRId64 ",compId:%{public}s,uid:%{public}s", formId, compId.c_str(), uid.c_str());
178     if (formId <= 0 || compId.empty() || uid.empty()) {
179         HILOG_ERROR("param invalid");
180         return ERR_APPEXECFWK_FORM_BIND_PROVIDER_FAILED;
181     }
182 
183     std::lock_guard<std::mutex> lock(renderRecordMutex_);
184     bool isRenderGroupEmpty = false;
185     auto search = renderRecordMap_.find(uid);
186     if (search == renderRecordMap_.end()) {
187         HILOG_ERROR("invalid record,formId:%{public}" PRId64, formId);
188         return RENDER_FORM_FAILED;
189     }
190 
191     if (!search->second) {
192         HILOG_ERROR("record invalid,formId:%{public}" PRId64, formId);
193         return RENDER_FORM_FAILED;
194     }
195 
196     search->second->ReleaseRenderer(formId, compId, isRenderGroupEmpty);
197     HILOG_INFO("end,isRenderGroupEmpty:%{public}d", isRenderGroupEmpty);
198     if (isRenderGroupEmpty) {
199         search->second->Release();
200     }
201 
202     return ERR_OK;
203 }
204 
CleanFormHost(const sptr<IRemoteObject> & hostToken)205 int32_t FormRenderImpl::CleanFormHost(const sptr<IRemoteObject> &hostToken)
206 {
207     HILOG_INFO("Form host is died,clean renderRecord");
208     std::lock_guard<std::mutex> lock(renderRecordMutex_);
209     for (auto iter = renderRecordMap_.begin(); iter != renderRecordMap_.end();) {
210         auto renderRecord = iter->second;
211         if (renderRecord && renderRecord->HandleHostDied(hostToken)) {
212             HILOG_DEBUG("empty renderRecord,remove");
213             iter = renderRecordMap_.erase(iter);
214         } else {
215             ++iter;
216         }
217     }
218     if (renderRecordMap_.empty()) {
219         HILOG_INFO("empty renderRecordMap_,FormRenderService will exit later");
220         FormMemmgrClient::GetInstance().SetCritical(false);
221     }
222     return ERR_OK;
223 }
224 
ReloadForm(const std::vector<FormJsInfo> && formJsInfos,const Want & want)225 int32_t FormRenderImpl::ReloadForm(const std::vector<FormJsInfo> &&formJsInfos, const Want &want)
226 {
227     HILOG_INFO("ReloadForm start");
228     std::lock_guard<std::mutex> lock(renderRecordMutex_);
229     std::string uid = want.GetStringParam(Constants::FORM_SUPPLY_UID);
230     if (uid.empty()) {
231         HILOG_ERROR("Get uid failed");
232         return ERR_APPEXECFWK_FORM_BIND_PROVIDER_FAILED;
233     }
234     auto search = renderRecordMap_.find(uid);
235     if (search == renderRecordMap_.end()) {
236         HILOG_ERROR("RenderRecord not find");
237         return RELOAD_FORM_FAILED;
238     }
239     if (search->second) {
240         search->second->ReloadFormRecord(std::forward<decltype(formJsInfos)>(formJsInfos), want);
241     }
242     return ERR_OK;
243 }
244 
OnUnlock()245 int32_t FormRenderImpl::OnUnlock()
246 {
247     HILOG_INFO("OnUnlock start");
248     std::lock_guard<std::mutex> lock(renderRecordMutex_);
249     if (isVerified_) {
250         HILOG_WARN("Has been unlocked in render form, maybe miss or delay unlock event");
251         return ERR_OK;
252     }
253 
254     isVerified_ = true;
255     for (const auto& iter : renderRecordMap_) {
256         if (iter.second) {
257             iter.second->OnUnlock();
258         }
259     }
260     return ERR_OK;
261 }
262 
SetVisibleChange(const int64_t & formId,bool isVisible,const Want & want)263 int32_t FormRenderImpl::SetVisibleChange(const int64_t &formId, bool isVisible, const Want &want)
264 {
265     HILOG_INFO("SetVisibleChange start");
266     if (formId <= 0) {
267         HILOG_ERROR("formId is negative");
268         return ERR_APPEXECFWK_FORM_INVALID_FORM_ID;
269     }
270 
271     std::string uid = want.GetStringParam(Constants::FORM_SUPPLY_UID);
272     if (uid.empty()) {
273         HILOG_ERROR("empty uid,formId:%{public}" PRId64, formId);
274         return ERR_APPEXECFWK_FORM_BIND_PROVIDER_FAILED;
275     }
276     HILOG_INFO("formId:%{public}" PRId64 ",uid:%{public}s", formId, uid.c_str());
277 
278     std::lock_guard<std::mutex> lock(renderRecordMutex_);
279     if (auto search = renderRecordMap_.find(uid); search != renderRecordMap_.end()) {
280         if (search->second == nullptr) {
281             HILOG_ERROR("null renderRecord of %{public}s", std::to_string(formId).c_str());
282             return SET_VISIBLE_CHANGE_FAILED;
283         }
284         auto ret = search->second->SetVisibleChange(formId, isVisible);
285         if (ret != ERR_OK) {
286             return ret;
287         }
288     } else {
289         HILOG_ERROR("can't find render record of %{public}s", std::to_string(formId).c_str());
290         return SET_VISIBLE_CHANGE_FAILED;
291     }
292     return ERR_OK;
293 }
294 
OnConfigurationUpdated(const std::shared_ptr<OHOS::AppExecFwk::Configuration> & configuration)295 void FormRenderImpl::OnConfigurationUpdated(
296     const std::shared_ptr<OHOS::AppExecFwk::Configuration>& configuration)
297 {
298     HILOG_DEBUG("OnConfigurationUpdated start");
299     std::lock_guard<std::mutex> lock(renderRecordMutex_);
300     if (!configuration) {
301         HILOG_ERROR("null configuration");
302         return;
303     }
304 
305     SetConfiguration(configuration);
306 
307 #ifdef SUPPORT_POWER
308     bool screenOnFlag = PowerMgr::PowerMgrClient::GetInstance().IsScreenOn();
309     bool collaborationScreenOnFlag = PowerMgr::PowerMgrClient::GetInstance().IsCollaborationScreenOn();
310     if (!screenOnFlag && !collaborationScreenOnFlag) {
311         HILOG_WARN("screen off");
312         hasCachedConfig_ = true;
313         return;
314     }
315 #endif
316 
317     constexpr int64_t minDurationMs = 1500;
318     const std::string taskName = "FormRenderImpl::OnConfigurationUpdated";
319     serialQueue_->CancelDelayTask(taskName);
320     auto duration = std::chrono::steady_clock::now() - configUpdateTime_;
321     if (std::chrono::duration_cast<std::chrono::milliseconds>(duration).count() < minDurationMs) {
322         HILOG_INFO("OnConfigurationUpdated ignored");
323         auto configUpdateFunc = [this]() {
324             HILOG_INFO("OnConfigurationUpdated task run");
325             this->OnConfigurationUpdatedInner();
326         };
327         constexpr int64_t taskDelayMs = 1000;
328         serialQueue_->ScheduleDelayTask(taskName, taskDelayMs, configUpdateFunc);
329         return;
330     }
331     OnConfigurationUpdatedInner();
332 }
333 
OnConfigurationUpdatedInner()334 void FormRenderImpl::OnConfigurationUpdatedInner()
335 {
336     sptr<IFormSupply> formSupplyClient = nullptr;
337     {
338         std::lock_guard<std::mutex> lock(formSupplyMutex_);
339         formSupplyClient = formSupplyClient_;
340     }
341     if (formSupplyClient == nullptr) {
342         HILOG_ERROR("null formSupplyClient");
343     }
344 
345     configUpdateTime_ = std::chrono::steady_clock::now();
346     size_t allFormCount = 0;
347     for (auto iter = renderRecordMap_.begin(); iter != renderRecordMap_.end(); ++iter) {
348         if (iter->second) {
349             iter->second->UpdateConfiguration(configuration_, formSupplyClient);
350             allFormCount += iter->second->FormCount();
351         }
352     }
353     HILOG_INFO("OnConfigurationUpdated %{public}zu forms updated.", allFormCount);
354     hasCachedConfig_ = false;
355     PerformanceEventInfo eventInfo;
356     eventInfo.timeStamp = FormRenderEventReport::GetNowMillisecond();
357     eventInfo.bundleName = Constants::FRS_BUNDLE_NAME;
358     eventInfo.sceneId = Constants::CPU_SCENE_ID_CONFIG_UPDATE;
359     FormRenderEventReport::SendPerformanceEvent(SceneType::CPU_SCENE_ENTRY, eventInfo);
360 }
361 
SetConfiguration(const std::shared_ptr<OHOS::AppExecFwk::Configuration> & config)362 void FormRenderImpl::SetConfiguration(const std::shared_ptr<OHOS::AppExecFwk::Configuration>& config)
363 {
364     if (config != nullptr && configuration_ != nullptr) {
365         std::string colorMode = config->GetItem(SYSTEM_COLORMODE);
366         std::string languageTag = config->GetItem(SYSTEM_LANGUAGE);
367         std::string colorModeOld = configuration_->GetItem(SYSTEM_COLORMODE);
368         std::string languageTagOld = configuration_->GetItem(SYSTEM_LANGUAGE);
369         configuration_ = config;
370         if (colorMode.empty()) {
371             configuration_->AddItem(SYSTEM_COLORMODE, colorModeOld);
372         }
373         if (languageTag.empty()) {
374             configuration_->AddItem(SYSTEM_LANGUAGE, languageTagOld);
375         }
376         return;
377     }
378 
379     configuration_ = config;
380 }
381 
RunCachedConfigurationUpdated()382 void FormRenderImpl::RunCachedConfigurationUpdated()
383 {
384     HILOG_INFO("RunCachedConfigUpdated");
385     std::lock_guard<std::mutex> lock(renderRecordMutex_);
386     if (hasCachedConfig_) {
387         OnConfigurationUpdatedInner();
388     }
389 }
390 
FormRenderGCTask(const std::string & uid)391 void FormRenderImpl::FormRenderGCTask(const std::string &uid)
392 {
393     auto mainHandler = std::make_shared<AppExecFwk::EventHandler>(AppExecFwk::EventRunner::GetMainEventRunner());
394     if (mainHandler == nullptr) {
395         HILOG_ERROR("null mainHandler");
396         return;
397     }
398     auto formRenderGCFunc = [uid]() {
399         auto formRenderImpl = OHOS::DelayedSingleton<FormRenderImpl>::GetInstance();
400         if (formRenderImpl == nullptr) {
401             HILOG_ERROR("null formRenderImpl");
402             return;
403         }
404         formRenderImpl->FormRenderGC(uid);
405     };
406     mainHandler->PostTask(formRenderGCFunc, "FormRenderGC", FORM_RENDER_TASK_DELAY_TIME);
407 }
408 
FormRenderGC(const std::string & uid)409 void FormRenderImpl::FormRenderGC(const std::string &uid)
410 {
411     HILOG_INFO("form gc, uid is %{s}public", uid.c_str());
412     std::lock_guard<std::mutex> lock(renderRecordMutex_);
413     if (auto search = renderRecordMap_.find(uid); search != renderRecordMap_.end()) {
414         search->second->FormRenderGC();
415     }
416 }
417 
RecycleForm(const int64_t & formId,const Want & want)418 int32_t FormRenderImpl::RecycleForm(const int64_t &formId, const Want &want)
419 {
420     if (formId <= 0) {
421         HILOG_ERROR("formId is negative");
422         return ERR_APPEXECFWK_FORM_INVALID_FORM_ID;
423     }
424 
425     std::string uid = want.GetStringParam(Constants::FORM_SUPPLY_UID);
426     if (uid.empty()) {
427         HILOG_ERROR("empty uid,formId:%{public}" PRId64, formId);
428         return ERR_APPEXECFWK_FORM_BIND_PROVIDER_FAILED;
429     }
430     HILOG_INFO("formId:%{public}" PRId64 ",uid:%{public}s", formId, uid.c_str());
431 
432     std::string statusData;
433     {
434         std::lock_guard<std::mutex> lock(renderRecordMutex_);
435         if (auto search = renderRecordMap_.find(uid); search != renderRecordMap_.end()) {
436             if (search->second == nullptr) {
437                 HILOG_ERROR("null renderRecord of %{public}s", std::to_string(formId).c_str());
438                 return RECYCLE_FORM_FAILED;
439             }
440             auto ret = search->second->RecycleForm(formId, statusData);
441             if (ret != ERR_OK) {
442                 return ret;
443             }
444         } else {
445             HILOG_ERROR("can't find render record of %{public}s", std::to_string(formId).c_str());
446             return RECYCLE_FORM_FAILED;
447         }
448         if (statusData.empty()) {
449             HILOG_WARN("empty statusData of %{public}s", std::to_string(formId).c_str());
450         }
451     }
452 
453     sptr<IFormSupply> formSupplyClient = nullptr;
454     {
455         std::lock_guard<std::mutex> lock(formSupplyMutex_);
456         formSupplyClient = formSupplyClient_;
457     }
458     if (formSupplyClient == nullptr) {
459         HILOG_ERROR("null formSupplyClient, formId:%{public}" PRId64, formId);
460         return RECYCLE_FORM_FAILED;
461     }
462 
463     Want newWant = want;
464     newWant.SetParam(Constants::FORM_STATUS_DATA, statusData);
465     formSupplyClient->OnRecycleForm(formId, newWant);
466     return ERR_OK;
467 }
468 
RecoverForm(const FormJsInfo & formJsInfo,const Want & want)469 int32_t FormRenderImpl::RecoverForm(const FormJsInfo &formJsInfo, const Want &want)
470 {
471     auto formId = formJsInfo.formId;
472     if (formId <= 0) {
473         HILOG_ERROR("formId is negative");
474         return ERR_APPEXECFWK_FORM_INVALID_FORM_ID;
475     }
476 
477     std::string uid = want.GetStringParam(Constants::FORM_SUPPLY_UID);
478     if (uid.empty()) {
479         HILOG_ERROR("empty uid,formId:%{public}" PRId64, formId);
480         return ERR_APPEXECFWK_FORM_BIND_PROVIDER_FAILED;
481     }
482     HILOG_INFO("formId:%{public}" PRId64 ", connectId:%{public}d, uid:%{public}s",
483         formId, want.GetIntParam(Constants::FORM_CONNECT_ID, 0L), uid.c_str());
484 
485     std::string statusData = want.GetStringParam(Constants::FORM_STATUS_DATA);
486     if (statusData.empty()) {
487         HILOG_WARN("empty statusData of %{public}s", std::to_string(formId).c_str());
488     }
489 
490     bool isRecoverFormToHandleClickEvent = want.GetBoolParam(
491         Constants::FORM_IS_RECOVER_FORM_TO_HANDLE_CLICK_EVENT, false);
492     std::lock_guard<std::mutex> lock(renderRecordMutex_);
493     if (auto search = renderRecordMap_.find(uid); search != renderRecordMap_.end()) {
494         if (search->second == nullptr) {
495             HILOG_ERROR("null renderRecord of %{public}s", std::to_string(formId).c_str());
496             return RECYCLE_FORM_FAILED;
497         }
498         return search->second->RecoverForm(formJsInfo, statusData, isRecoverFormToHandleClickEvent);
499     }
500     HILOG_ERROR("can't find render record of %{public}s", std::to_string(formId).c_str());
501     return RENDER_FORM_FAILED;
502 }
503 
ConfirmUnlockState(Want & renderWant)504 void FormRenderImpl::ConfirmUnlockState(Want &renderWant)
505 {
506     // Ensure that there are no issues with adding form and unlocking drawing concurrency
507     if (isVerified_) {
508         renderWant.SetParam(Constants::FORM_RENDER_STATE, true);
509     } else if (renderWant.GetBoolParam(Constants::FORM_RENDER_STATE, false)) {
510         HILOG_WARN("Maybe unlock event is missed or delayed, all form record begin to render");
511         isVerified_ = true;
512         for (const auto& iter : renderRecordMap_) {
513             if (iter.second) {
514                 iter.second->OnUnlock();
515             }
516         }
517     }
518 }
519 } // namespace FormRender
520 } // namespace AppExecFwk
521 } // namespace OHOS
522