• 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_mgr.h"
17 
18 #include "form_ams_helper.h"
19 #include "form_bms_helper.h"
20 #include "form_cache_mgr.h"
21 #include "form_constants.h"
22 #include "form_data_mgr.h"
23 #include "form_host_interface.h"
24 #include "form_mgr_errors.h"
25 #include "form_supply_callback.h"
26 #include "form_task_mgr.h"
27 #include "form_util.h"
28 #include "hilog_wrapper.h"
29 #include "ipc_skeleton.h"
30 #include "want.h"
31 
32 namespace OHOS {
33 namespace AppExecFwk {
34 namespace {
35     constexpr size_t LAST_CONNECTION = 1;
36 }
37 using Want = OHOS::AAFwk::Want;
FormRenderMgr()38 FormRenderMgr::FormRenderMgr()
39 {
40 }
~FormRenderMgr()41 FormRenderMgr::~FormRenderMgr()
42 {
43 }
RenderForm(const FormRecord & formRecord,const WantParams & wantParams,const sptr<IRemoteObject> & hostToken)44 ErrCode FormRenderMgr::RenderForm(
45     const FormRecord &formRecord, const WantParams &wantParams, const sptr<IRemoteObject> &hostToken)
46 {
47     HILOG_INFO("RenderForm formId: %{public}" PRId64 "", formRecord.formId);
48     if (formRecord.uiSyntax != FormType::ETS) {
49         return ERR_OK;
50     }
51 
52     if (formRecord.formId <= 0) {
53         HILOG_ERROR("%{public}s fail, formId should be greater than 0.", __func__);
54         return ERR_APPEXECFWK_FORM_INVALID_PARAM;
55     }
56 
57     int32_t userId = FormUtil::GetCurrentAccountId();
58     Want want;
59     want.SetParams(wantParams);
60     want.SetParam(Constants::FORM_SUPPLY_UID, std::to_string(userId) + formRecord.bundleName);
61     if (atomicRerenderCount_ > 0) {
62         --atomicRerenderCount_;
63     } else {
64         atomicRerenderCount_ = 0;
65     }
66     if (hostToken) {
67         HILOG_DEBUG("Add host token");
68         AddHostToken(hostToken, formRecord.formId);
69         want.SetParam(Constants::PARAM_FORM_HOST_TOKEN, hostToken);
70     }
71 
72     bool connectionExisted = false;
73     sptr<FormRenderConnection> connection = nullptr;
74     {
75         std::lock_guard<std::mutex> lock(resourceMutex_);
76         HILOG_DEBUG("renderFormConnections_ size: %{public}zu.", renderFormConnections_.size());
77         auto conIterator = renderFormConnections_.find(formRecord.formId);
78         if (conIterator != renderFormConnections_.end()) {
79             connectionExisted = true;
80             connection = conIterator->second;
81         }
82     }
83     if (connectionExisted) {
84         if (connection == nullptr) {
85             HILOG_ERROR("connection is null.");
86             return ERR_APPEXECFWK_FORM_INVALID_PARAM;
87         }
88         if (renderRemoteObj_ == nullptr) {
89             connection->UpdateWantParams(want.GetParams());
90             ErrCode ret = ConnectRenderService(connection);
91             HILOG_INFO("renderRemoteObj is nullptr, render may exit, need reconnect, ret: %{public}d.", ret);
92             if (ret) {
93                 HandleConnectFailed(formRecord.formId, ret);
94             }
95             return ret;
96         }
97         auto remoteObject = renderRemoteObj_->AsObject();
98         if (remoteObject == nullptr) {
99             HILOG_ERROR("remoteObject is nullptr, can not get obj from renderRemoteObj.");
100             return ERR_APPEXECFWK_FORM_INVALID_PARAM;
101         }
102         want.SetParam(Constants::FORM_CONNECT_ID, connection->GetConnectId());
103         FormTaskMgr::GetInstance().PostRenderForm(formRecord, want, remoteObject);
104         return ERR_OK;
105     }
106 
107     auto formRenderConnection = new (std::nothrow) FormRenderConnection(formRecord, want.GetParams());
108     if (formRenderConnection == nullptr) {
109         HILOG_ERROR("formRenderConnection is null.");
110         return ERR_APPEXECFWK_FORM_BIND_PROVIDER_FAILED;
111     }
112     ErrCode errorCode = ConnectRenderService(formRenderConnection);
113     if (errorCode != ERR_OK) {
114         HILOG_ERROR("%{public}s fail, ConnectServiceAbility failed.", __func__);
115         HandleConnectFailed(formRecord.formId, errorCode);
116         return ERR_APPEXECFWK_FORM_BIND_PROVIDER_FAILED;
117     }
118     return ERR_OK;
119 }
120 
UpdateRenderingForm(int64_t formId,const FormProviderData & formProviderData,const WantParams & wantParams,bool mergeData)121 ErrCode FormRenderMgr::UpdateRenderingForm(int64_t formId, const FormProviderData &formProviderData,
122     const WantParams &wantParams, bool mergeData)
123 {
124     HILOG_DEBUG("RenderForm with formId.");
125     FormRecord formRecord;
126     bool isGetFormRecord = FormDataMgr::GetInstance().GetFormRecord(formId, formRecord);
127     if (!isGetFormRecord) {
128         HILOG_ERROR("%{public}s fail, not exist such form, formId:%{public}" PRId64 "", __func__, formId);
129         return ERR_APPEXECFWK_FORM_NOT_EXIST_ID;
130     }
131     if (mergeData) {
132         nlohmann::json jsonData = formProviderData.GetData();
133         formRecord.formProviderInfo.MergeData(jsonData);
134         auto providerData = formRecord.formProviderInfo.GetFormData();
135         providerData.SetImageDataState(formProviderData.GetImageDataState());
136         providerData.SetImageDataMap(formProviderData.GetImageDataMap());
137         formRecord.formProviderInfo.SetFormData(providerData);
138     } else {
139         formRecord.formProviderInfo.SetFormData(formProviderData);
140     }
141 
142     if (formRecord.formProviderInfo.NeedCache()) {
143         std::string jsonData = formRecord.formProviderInfo.GetFormDataString();
144         HILOG_DEBUG("%{public}s, jsonData is %{private}s.", __func__, jsonData.c_str());
145         FormCacheMgr::GetInstance().AddData(formId, jsonData);
146     }
147     FormDataMgr::GetInstance().SetFormCacheInited(formId, true);
148 
149     Want want;
150     want.SetParams(wantParams);
151     want.SetParam(Constants::FORM_RENDER_TYPE_KEY, Constants::UPDATE_RENDERING_FORM);
152     int32_t userId = FormUtil::GetCurrentAccountId();
153     want.SetParam(Constants::FORM_SUPPLY_UID, std::to_string(userId) + formRecord.bundleName);
154     {
155         std::lock_guard<std::mutex> lock(resourceMutex_);
156         auto conIterator = renderFormConnections_.find(formRecord.formId);
157         if (conIterator != renderFormConnections_.end()) {
158             auto connection = conIterator->second;
159             if (connection == nullptr) {
160                 HILOG_ERROR("connection is null.");
161                 return ERR_APPEXECFWK_FORM_INVALID_PARAM;
162             }
163             if (renderRemoteObj_ == nullptr) {
164                 HILOG_ERROR("%{public}s, renderRemoteObj_ is nullptr", __func__);
165                 return ERR_APPEXECFWK_FORM_INVALID_PARAM;
166             }
167             auto remoteObject = renderRemoteObj_->AsObject();
168             if (remoteObject == nullptr) {
169                 HILOG_ERROR("remoteObject is nullptr, can not get obj from renderRemoteObj.");
170                 return ERR_APPEXECFWK_FORM_INVALID_PARAM;
171             }
172             want.SetParam(Constants::FORM_CONNECT_ID, connection->GetConnectId());
173             FormTaskMgr::GetInstance().PostRenderForm(formRecord, std::move(want), remoteObject);
174             return ERR_OK;
175         }
176     }
177     return ERR_APPEXECFWK_FORM_INVALID_PARAM;
178 }
179 
ReloadForm(std::vector<int64_t> && formIds,const std::string & bundleName,int32_t userId)180 ErrCode FormRenderMgr::ReloadForm(std::vector<int64_t> &&formIds, const std::string &bundleName, int32_t userId)
181 {
182     if (renderRemoteObj_ == nullptr) {
183         HILOG_ERROR("%{public}s, renderRemoteObj_ is nullptr", __func__);
184         return ERR_APPEXECFWK_FORM_INVALID_PARAM;
185     }
186     auto remoteObject = renderRemoteObj_->AsObject();
187     if (remoteObject == nullptr) {
188         HILOG_ERROR("remoteObject is nullptr, can not get obj from renderRemoteObj.");
189         return ERR_APPEXECFWK_FORM_INVALID_PARAM;
190     }
191     Want want;
192     want.SetParam(Constants::FORM_SUPPLY_UID, std::to_string(userId) + bundleName);
193     FormTaskMgr::GetInstance().PostReloadForm(std::forward<decltype(formIds)>(formIds), want, remoteObject);
194     return ERR_OK;
195 }
196 
StopRenderingForm(int64_t formId,const FormRecord & formRecord,const std::string & compId,const sptr<IRemoteObject> & hostToken)197 ErrCode FormRenderMgr::StopRenderingForm(int64_t formId, const FormRecord &formRecord, const std::string &compId, const sptr<IRemoteObject> &hostToken)
198 {
199     HILOG_DEBUG("%{public}s called.", __func__);
200     if (formRecord.uiSyntax != FormType::ETS) {
201         return ERR_OK;
202     }
203     if (formRecord.abilityName.empty()) {
204         HILOG_ERROR("%{public}s, formRecord.abilityName is empty.", __func__);
205         return ERR_APPEXECFWK_FORM_INVALID_PARAM;
206     }
207     if (formRecord.bundleName.empty()) {
208         HILOG_ERROR("%{public}s, formRecord.bundleName is empty.", __func__);
209         return ERR_APPEXECFWK_FORM_INVALID_PARAM;
210     }
211     Want want;
212     int32_t userId = FormUtil::GetCurrentAccountId();
213     want.SetParam(Constants::FORM_SUPPLY_UID, std::to_string(userId) + formRecord.bundleName);
214     if (!compId.empty()) {
215         want.SetParam(Constants::FORM_RENDER_COMP_ID, compId);
216     }
217     if (hostToken) {
218         HILOG_DEBUG("StopRenderingForm Add host token");
219         want.SetParam(Constants::PARAM_FORM_HOST_TOKEN, hostToken);
220     }
221 
222     {
223         std::lock_guard<std::mutex> lock(resourceMutex_);
224         auto conIterator = renderFormConnections_.find(formRecord.formId);
225         if (conIterator != renderFormConnections_.end()) {
226             auto connection = conIterator->second;
227             if (connection == nullptr) {
228                 HILOG_ERROR("connection is null.");
229                 return ERR_APPEXECFWK_FORM_INVALID_PARAM;
230             }
231             if (renderRemoteObj_ == nullptr) {
232                 HILOG_ERROR("%{public}s, renderRemoteObj_ is nullptr", __func__);
233                 return ERR_APPEXECFWK_FORM_INVALID_PARAM;
234             }
235             auto remoteObject = renderRemoteObj_->AsObject();
236             if (remoteObject == nullptr) {
237                 HILOG_ERROR("remoteObject is nullptr, can not get obj from renderRemoteObj.");
238                 return ERR_APPEXECFWK_FORM_INVALID_PARAM;
239             }
240             want.SetParam(Constants::FORM_CONNECT_ID, connection->GetConnectId());
241             FormTaskMgr::GetInstance().PostStopRenderingForm(formRecord, std::move(want), remoteObject);
242             return ERR_OK;
243         }
244     }
245     return ERR_APPEXECFWK_FORM_INVALID_PARAM;
246 }
247 
RenderFormCallback(int64_t formId,const Want & want)248 ErrCode FormRenderMgr::RenderFormCallback(int64_t formId, const Want &want)
249 {
250     HILOG_INFO("%{public}s called.", __func__);
251     return ERR_OK;
252 }
253 
StopRenderingFormCallback(int64_t formId,const Want & want)254 ErrCode FormRenderMgr::StopRenderingFormCallback(int64_t formId, const Want &want)
255 {
256     HILOG_INFO("%{public}s called.", __func__);
257     sptr<FormRenderConnection> stopConnection = nullptr;
258     std::lock_guard<std::mutex> lock(resourceMutex_);
259     {
260         HILOG_DEBUG("renderFormConnections_ size: %{public}zu.", renderFormConnections_.size());
261         auto conIterator = renderFormConnections_.find(formId);
262         if (conIterator == renderFormConnections_.end()) {
263             HILOG_ERROR("Can not find formId in map.");
264             return ERR_APPEXECFWK_FORM_INVALID_PARAM;
265         }
266         stopConnection = conIterator->second;
267     }
268     if (stopConnection == nullptr) {
269         HILOG_ERROR("Can not find stopConnection in map.");
270         return ERR_APPEXECFWK_FORM_INVALID_PARAM;
271     }
272     DisconnectRenderService(stopConnection, renderFormConnections_.size());
273 
274     for (auto iter = etsHosts_.begin(); iter != etsHosts_.end();) {
275         iter->second.erase(formId);
276         if (iter->second.empty()) {
277             HILOG_INFO("All forms of the host have been removed, remove the host.");
278             iter = etsHosts_.erase(iter);
279         } else {
280             ++iter;
281         }
282     }
283     renderFormConnections_.erase(formId);
284     return ERR_OK;
285 }
286 
AddConnection(int64_t formId,sptr<FormRenderConnection> connection)287 ErrCode FormRenderMgr::AddConnection(int64_t formId, sptr<FormRenderConnection> connection)
288 {
289     HILOG_INFO("%{public}s called.", __func__);
290     if (connection == nullptr) {
291         HILOG_ERROR("Input FormRenderConnection is nullptr.");
292         return ERR_APPEXECFWK_FORM_INVALID_PARAM;
293     }
294     {
295         int32_t connectKey = static_cast<int32_t>(FormUtil::GetCurrentMillisecond());
296         std::lock_guard<std::mutex> lock(resourceMutex_);
297         if (connectKey <= maxConnectKey) {
298             connectKey = maxConnectKey + 1;
299             maxConnectKey = connectKey;
300         }
301         connection->SetConnectId(connectKey);
302         auto conIterator = renderFormConnections_.find(formId);
303         if (conIterator == renderFormConnections_.end()) {
304             renderFormConnections_.emplace(formId, connection);
305             conIterator = renderFormConnections_.begin();
306         }
307 
308         renderFormConnections_[formId] = connection;
309         HILOG_DEBUG("renderFormConnections size: %{public}zu.", renderFormConnections_.size());
310     }
311     return ERR_OK;
312 }
313 
RerenderAllForms()314 void FormRenderMgr::RerenderAllForms()
315 {
316     HILOG_INFO("Render is dead.");
317     renderRemoteObj_ = nullptr;
318 
319     {
320         std::lock_guard<std::mutex> lock(resourceMutex_);
321         atomicRerenderCount_ = renderFormConnections_.size();
322         if (etsHosts_.empty() || renderFormConnections_.empty()) {
323             HILOG_INFO("All hosts died or all connections erased, no need to rerender.");
324             return;
325         }
326         HILOG_INFO("The forms need to rerender count: %{public}zu.", renderFormConnections_.size());
327         for (auto &item : renderFormConnections_) {
328             if (item.second == nullptr) {
329                 HILOG_ERROR("Connection is nullptr.");
330                 continue;
331             }
332             item.second->SetStateDisconnected();
333         }
334     }
335 
336     NotifyHostRenderServiceIsDead();
337 }
338 
CleanFormHost(const sptr<IRemoteObject> & host)339 void FormRenderMgr::CleanFormHost(const sptr<IRemoteObject> &host)
340 {
341     HILOG_INFO("Host is died or been removed, notify FormRenderService and remove host.");
342     RemoveHostToken(host);
343     if (renderRemoteObj_ == nullptr) {
344         HILOG_WARN("renderRemoteObj is nullptr, render service may exit already.");
345         return;
346     }
347     renderRemoteObj_->CleanFormHost(host);
348 }
349 
AddRenderDeathRecipient(const sptr<IRemoteObject> & remoteObject)350 void FormRenderMgr::AddRenderDeathRecipient(const sptr<IRemoteObject> &remoteObject)
351 {
352     if (renderRemoteObj_) {
353         HILOG_INFO("renderDeathRecipient is exist, no need to add again.");
354         return;
355     }
356 
357     HILOG_INFO("Get renderRemoteObj, add death recipient.");
358     auto renderRemoteObj = iface_cast<IFormRender>(remoteObject);
359     if (renderRemoteObj == nullptr) {
360         HILOG_ERROR("renderRemoteObj is nullptr.");
361         return;
362     }
363     renderRemoteObj_ = renderRemoteObj;
364 
365     if (renderDeathRecipient_ == nullptr) {
366         renderDeathRecipient_ = new FormRenderRecipient([]() {
367             FormRenderMgr::GetInstance().RerenderAllForms();
368         });
369     }
370     remoteObject->AddDeathRecipient(renderDeathRecipient_);
371 }
372 
ConnectRenderService(const sptr<FormRenderConnection> & connection) const373 inline ErrCode FormRenderMgr::ConnectRenderService(const sptr<FormRenderConnection> &connection) const
374 {
375     if (connection == nullptr) {
376         HILOG_INFO("connection is nullptr.");
377         return ERR_APPEXECFWK_FORM_INVALID_PARAM;
378     }
379     Want want;
380     want.SetElementName("com.ohos.formrenderservice", "ServiceExtension");
381     want.AddFlags(Want::FLAG_ABILITY_FORM_ENABLED);
382     connection->SetStateConnecting();
383     return FormAmsHelper::GetInstance().ConnectServiceAbility(want, connection);
384 }
385 
DisconnectRenderService(const sptr<FormRenderConnection> connection,size_t size) const386 void FormRenderMgr::DisconnectRenderService(const sptr<FormRenderConnection> connection, size_t size) const
387 {
388     if (size == LAST_CONNECTION) {
389         HILOG_INFO("This is the last connection, disconnect render service delay");
390         FormAmsHelper::GetInstance().DisconnectServiceAbilityDelay(connection);
391     } else {
392         HILOG_DEBUG("Disconnect render service ability");
393         FormAmsHelper::GetInstance().DisconnectServiceAbility(connection);
394     }
395 }
396 
IsNeedRender(int64_t formId)397 bool FormRenderMgr::IsNeedRender(int64_t formId)
398 {
399     FormRecord formRecord;
400     bool isGetFormRecord = FormDataMgr::GetInstance().GetFormRecord(formId, formRecord);
401     if (!isGetFormRecord) {
402         HILOG_ERROR("%{public}s fail, not exist such form, formId:%{public}" PRId64 "", __func__, formId);
403         return false;
404     }
405     if (formRecord.uiSyntax != FormType::ETS) {
406         HILOG_DEBUG("%{public}s fail, no need render, formId:%{public}" PRId64 "", __func__, formId);
407         return false;
408     }
409     return true;
410 }
411 
AddHostToken(const sptr<IRemoteObject> & host,int64_t formId)412 inline void FormRenderMgr::AddHostToken(const sptr<IRemoteObject> &host, int64_t formId)
413 {
414     {
415         std::lock_guard<std::mutex> lock(resourceMutex_);
416         auto iter = etsHosts_.find(host);
417         if (iter == etsHosts_.end()) {
418             HILOG_DEBUG("Add host, current etsHosts.size: %{public}zu.", etsHosts_.size());
419             std::unordered_set<int64_t> formIdSet;
420             formIdSet.emplace(formId);
421             etsHosts_.emplace(host, formIdSet);
422         } else {
423             HILOG_DEBUG("Add formId to host, current etsHosts.size: %{public}zu.", etsHosts_.size());
424             iter->second.emplace(formId);
425         }
426     }
427 }
428 
RemoveHostToken(const sptr<IRemoteObject> & host)429 void FormRenderMgr::RemoveHostToken(const sptr<IRemoteObject> &host)
430 {
431     HILOG_DEBUG("Remove host, current etsHosts.size: %{public}zu.", etsHosts_.size());
432 
433     std::lock_guard<std::mutex> lock(resourceMutex_);
434     auto iter = etsHosts_.find(host);
435     if (iter == etsHosts_.end()) {
436         HILOG_ERROR("Can not find host in etsHosts.");
437         return;
438     }
439     auto formIdSet = iter->second;
440     for (const int64_t formId : formIdSet) {
441         auto connection = renderFormConnections_[formId];
442         FormRecord formRecord;
443         if (!FormDataMgr::GetInstance().GetFormRecord(formId, formRecord)) {
444             // hosts of this formId is empty, remove formId
445             DisconnectRenderService(connection, renderFormConnections_.size());
446             renderFormConnections_.erase(formId);
447         }
448     }
449     etsHosts_.erase(host);
450     if (etsHosts_.empty()) {
451         HILOG_DEBUG("etsHosts is empty, disconnect all connections, current connection.size: %{public}zu.",
452             renderFormConnections_.size());
453         for (auto iterConnection = renderFormConnections_.begin(); iterConnection != renderFormConnections_.end();) {
454             DisconnectRenderService(iterConnection->second, renderFormConnections_.size());
455             iterConnection = renderFormConnections_.erase(iterConnection);
456         }
457     }
458 }
459 
NotifyHostRenderServiceIsDead() const460 void FormRenderMgr::NotifyHostRenderServiceIsDead() const
461 {
462     HILOG_INFO("Notify hosts the render is dead, hosts.size: %{public}zu.", etsHosts_.size());
463     for (const auto &item : etsHosts_) {
464         auto hostClient = iface_cast<IFormHost>(item.first);
465         if (hostClient == nullptr) {
466             HILOG_ERROR("hostClient is nullptr");
467             continue;
468         }
469         hostClient->OnError(ERR_APPEXECFWK_FORM_RENDER_SERVICE_DIED, "FormRenderService is dead.");
470     }
471 }
472 
HandleConnectFailed(int64_t formId,int32_t errorCode) const473 void FormRenderMgr::HandleConnectFailed(int64_t formId, int32_t errorCode) const
474 {
475     HILOG_ERROR("Connect render service failed, formId: %{public}" PRId64 ", errorCode: %{public}d",
476         formId, errorCode);
477     std::vector<sptr<IRemoteObject>> formHostObjs;
478     FormDataMgr::GetInstance().GetFormHostRemoteObj(formId, formHostObjs);
479     for (const auto &host : formHostObjs) {
480         auto hostClient = iface_cast<IFormHost>(host);
481         if (hostClient == nullptr) {
482             HILOG_ERROR("hostClient is nullptr");
483             continue;
484         }
485         hostClient->OnError(errorCode, "Connect FormRenderService failed");
486     }
487 }
488 
IsRerenderForRenderServiceDied(int64_t formId)489 bool FormRenderMgr::IsRerenderForRenderServiceDied(int64_t formId)
490 {
491     bool ret = IsNeedRender(formId) && (atomicRerenderCount_ > 0);
492     HILOG_DEBUG("Is need to rerender: %{public}d.", ret);
493     return ret;
494 }
495 
OnRemoteDied(const wptr<IRemoteObject> & remote)496 void FormRenderRecipient::OnRemoteDied(const wptr<IRemoteObject> &remote)
497 {
498     HILOG_ERROR("Recv FormRenderService death notice");
499 
500     if (handler_) {
501         handler_();
502     }
503 }
504 
FormRenderRecipient(RemoteDiedHandler handler)505 FormRenderRecipient::FormRenderRecipient(RemoteDiedHandler handler) : handler_(handler) {}
506 
~FormRenderRecipient()507 FormRenderRecipient::~FormRenderRecipient() {}
508 } // namespace AppExecFwk
509 } // namespace OHOS
510