1 /*
2 * Copyright (c) 2021-2022 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_host_client.h"
17
18 #include <cinttypes>
19
20 #include "hilog_wrapper.h"
21 #include "hitrace_meter.h"
22 #include "form_constants.h"
23 #include "form_caller_mgr.h"
24
25 namespace OHOS {
26 namespace AppExecFwk {
27 sptr<FormHostClient> FormHostClient::instance_ = nullptr;
28 std::mutex FormHostClient::instanceMutex_;
29
FormHostClient()30 FormHostClient::FormHostClient()
31 {
32 }
33
~FormHostClient()34 FormHostClient::~FormHostClient()
35 {
36 }
37
38 /**
39 * @brief Get FormHostClient instance.
40 *
41 * @return FormHostClient instance.
42 */
GetInstance()43 sptr<FormHostClient> FormHostClient::GetInstance()
44 {
45 if (instance_ == nullptr) {
46 std::lock_guard<std::mutex> lock_l(instanceMutex_);
47 if (instance_ == nullptr) {
48 instance_ = new (std::nothrow) FormHostClient();
49 if (instance_ == nullptr) {
50 HILOG_ERROR("%{public}s error, failed to create FormHostClient.", __func__);
51 }
52 }
53 }
54 return instance_;
55 }
56
57 /**
58 * @brief Add form callback.
59 *
60 * @param formCallback the host's form callback.
61 * @param formId The Id of the form.
62 * @return none.
63 */
AddForm(std::shared_ptr<FormCallbackInterface> formCallback,const FormJsInfo & formJsInfo)64 void FormHostClient::AddForm(std::shared_ptr<FormCallbackInterface> formCallback, const FormJsInfo &formJsInfo)
65 {
66 auto formId = formJsInfo.formId;
67 HILOG_INFO("%{public}s called, formId: %{public}" PRId64 ".", __func__, formId);
68 if (formId <= 0 || formCallback == nullptr) {
69 HILOG_ERROR("%{public}s error, invalid formId or formCallback.", __func__);
70 return;
71 }
72 std::lock_guard<std::mutex> lock(callbackMutex_);
73 auto iter = formCallbackMap_.find(formId);
74 if (iter == formCallbackMap_.end()) {
75 std::set<std::shared_ptr<FormCallbackInterface>> callbacks;
76 callbacks.emplace(formCallback);
77 formCallbackMap_.emplace(formId, callbacks);
78 } else {
79 iter->second.emplace(formCallback);
80 }
81
82 if (formJsInfo.uiSyntax == FormType::ETS) {
83 etsFormIds_.emplace(formId);
84 }
85 }
86
87 /**
88 * @brief Remove form callback.
89 *
90 * @param formCallback the host's form callback.
91 * @param formId The Id of the form.
92 * @return none.
93 */
RemoveForm(std::shared_ptr<FormCallbackInterface> formCallback,const int64_t formId)94 void FormHostClient::RemoveForm(std::shared_ptr<FormCallbackInterface> formCallback, const int64_t formId)
95 {
96 HILOG_INFO("%{public}s called, formId: %{public}" PRId64 ".", __func__, formId);
97 if (formId <= 0 || formCallback == nullptr) {
98 HILOG_ERROR("%{public}s, invalid formId or formCallback.", __func__);
99 return;
100 }
101 std::lock_guard<std::mutex> lock(callbackMutex_);
102 auto iter = formCallbackMap_.find(formId);
103 if (iter == formCallbackMap_.end()) {
104 HILOG_ERROR("%{public}s, not find formId:%{public}s.", __func__, std::to_string(formId).c_str());
105 return;
106 }
107 iter->second.erase(formCallback);
108 if (iter->second.empty()) {
109 HILOG_INFO("All callbacks have been removed, remove formId");
110 formCallbackMap_.erase(iter);
111 etsFormIds_.erase(formId);
112 }
113 }
114
115 /**
116 * @brief Check whether the form exist in the formhosts.
117 *
118 * @param formId The Id of the form.
119 * @return Returns true if contains form; returns false otherwise.
120 */
ContainsForm(int64_t formId)121 bool FormHostClient::ContainsForm(int64_t formId)
122 {
123 HILOG_INFO("%{public}s called.", __func__);
124 std::lock_guard<std::mutex> lock(callbackMutex_);
125 return formCallbackMap_.find(formId) != formCallbackMap_.end();
126 }
127
128 /**
129 * @brief Add form state.
130 *
131 * @param formStateCallback the host's form state callback.
132 * @param want the want of acquiring form state.
133 * @return Returns true if contains form; returns false otherwise.
134 */
AddFormState(const std::shared_ptr<FormStateCallbackInterface> & formStateCallback,const AAFwk::Want & want)135 bool FormHostClient::AddFormState(const std::shared_ptr<FormStateCallbackInterface> &formStateCallback,
136 const AAFwk::Want &want)
137 {
138 HILOG_INFO("%{public}s called.", __func__);
139 std::string bundleName = want.GetElement().GetBundleName();
140 std::string abilityName = want.GetElement().GetAbilityName();
141 const std::string doubleColon = "::";
142 std::string key;
143 key.append(bundleName).append(doubleColon).append(abilityName).append(doubleColon)
144 .append(want.GetStringParam(AppExecFwk::Constants::PARAM_MODULE_NAME_KEY)).append(doubleColon)
145 .append(want.GetStringParam(AppExecFwk::Constants::PARAM_FORM_NAME_KEY)).append(doubleColon)
146 .append(std::to_string(want.GetIntParam(AppExecFwk::Constants::PARAM_FORM_DIMENSION_KEY, 1)));
147 std::lock_guard<std::mutex> lock(formStateCallbackMutex_);
148 auto iter = formStateCallbackMap_.find(key);
149 if (iter == formStateCallbackMap_.end()) {
150 std::set<std::shared_ptr<FormStateCallbackInterface>> callbacks;
151 callbacks.emplace(formStateCallback);
152 formStateCallbackMap_.emplace(key, callbacks);
153 } else {
154 iter->second.insert(formStateCallback);
155 }
156 HILOG_INFO("%{public}s done.", __func__);
157 return true;
158 }
159
RemoveFormState(const AAFwk::Want & want)160 void FormHostClient::RemoveFormState(const AAFwk::Want &want)
161 {
162 HILOG_INFO("%{public}s called.", __func__);
163 std::string bundleName = want.GetElement().GetBundleName();
164 std::string abilityName = want.GetElement().GetAbilityName();
165 const std::string doubleColon = "::";
166 std::string key;
167 key.append(bundleName).append(doubleColon).append(abilityName).append(doubleColon)
168 .append(want.GetStringParam(AppExecFwk::Constants::PARAM_MODULE_NAME_KEY)).append(doubleColon)
169 .append(want.GetStringParam(AppExecFwk::Constants::PARAM_FORM_NAME_KEY)).append(doubleColon)
170 .append(std::to_string(want.GetIntParam(AppExecFwk::Constants::PARAM_FORM_DIMENSION_KEY, 1)));
171 std::lock_guard<std::mutex> lock(formStateCallbackMutex_);
172 auto iter = formStateCallbackMap_.find(key);
173 if (iter != formStateCallbackMap_.end()) {
174 formStateCallbackMap_.erase(key);
175 }
176 HILOG_INFO("%{public}s end.", __func__);
177 }
178
RegisterUninstallCallback(UninstallCallback callback)179 bool FormHostClient::RegisterUninstallCallback(UninstallCallback callback)
180 {
181 std::lock_guard<std::mutex> lock(uninstallCallbackMutex_);
182 uninstallCallback_ = callback;
183 return true;
184 }
185
OnAcquired(const FormJsInfo & formJsInfo,const sptr<IRemoteObject> & token)186 void FormHostClient::OnAcquired(const FormJsInfo &formJsInfo, const sptr<IRemoteObject> &token)
187 {
188 HILOG_DEBUG("%{public}s called.", __func__);
189 if (token != nullptr) {
190 HILOG_DEBUG("save token to form remote mgr.");
191 FormCallerMgr::GetInstance().AddFormHostCaller(formJsInfo, token);
192 }
193 UpdateForm(formJsInfo);
194 }
195
196 /**
197 * @brief Update form.
198 *
199 * @param formJsInfo Form js info.
200 * @return none.
201 */
OnUpdate(const FormJsInfo & formJsInfo)202 void FormHostClient::OnUpdate(const FormJsInfo &formJsInfo)
203 {
204 HILOG_DEBUG("%{public}s called.", __func__);
205 UpdateForm(formJsInfo);
206 }
207
208 /**
209 * @brief UnInstall the forms.
210 *
211 * @param formIds The Id of the forms.
212 * @return none.
213 */
OnUninstall(const std::vector<int64_t> & formIds)214 void FormHostClient::OnUninstall(const std::vector<int64_t> &formIds)
215 {
216 HILOG_INFO("%{public}s called.", __func__);
217 if (formIds.empty()) {
218 HILOG_ERROR("%{public}s error, formIds is empty.", __func__);
219 return;
220 }
221 {
222 std::lock_guard<std::mutex> lock(uninstallCallbackMutex_);
223 if (uninstallCallback_ != nullptr) {
224 uninstallCallback_(formIds);
225 }
226 }
227 for (auto &formId : formIds) {
228 if (formId < 0) {
229 HILOG_ERROR("%{public}s error, the passed form id can't be negative.", __func__);
230 continue;
231 }
232 std::lock_guard<std::mutex> lock(callbackMutex_);
233 auto iter = formCallbackMap_.find(formId);
234 if (iter == formCallbackMap_.end()) {
235 HILOG_ERROR("%{public}s error, not find formId:%{public}s.", __func__, std::to_string(formId).c_str());
236 continue;
237 }
238 for (const auto& callback : iter->second) {
239 HILOG_ERROR("%{public}s uninstall formId:%{public}s.", __func__, std::to_string(formId).c_str());
240 callback->ProcessFormUninstall(formId);
241 }
242 }
243 }
244
245 /**
246 * @brief Form provider is acquire state
247 * @param state The form state.
248 * @param want The form want.
249 */
OnAcquireState(FormState state,const AAFwk::Want & want)250 void FormHostClient::OnAcquireState(FormState state, const AAFwk::Want &want)
251 {
252 HILOG_INFO("%{public}s state:%{public}d.", __func__, state);
253 std::string bundleName = want.GetElement().GetBundleName();
254 std::string abilityName = want.GetElement().GetAbilityName();
255 const std::string doubleColon = "::";
256 std::string key;
257 key.append(bundleName).append(doubleColon).append(abilityName).append(doubleColon)
258 .append(want.GetStringParam(AppExecFwk::Constants::PARAM_MODULE_NAME_KEY)).append(doubleColon)
259 .append(want.GetStringParam(AppExecFwk::Constants::PARAM_FORM_NAME_KEY)).append(doubleColon)
260 .append(std::to_string(want.GetIntParam(AppExecFwk::Constants::PARAM_FORM_DIMENSION_KEY, 1)));
261
262 std::lock_guard<std::mutex> lock(formStateCallbackMutex_);
263 auto iter = formStateCallbackMap_.find(key);
264 if (iter == formStateCallbackMap_.end()) {
265 HILOG_INFO("form state callback not found");
266 } else {
267 std::set<std::shared_ptr<FormStateCallbackInterface>> &callbackSet = iter->second;
268 for (auto &callback: callbackSet) {
269 callback->ProcessAcquireState(state);
270 }
271 formStateCallbackMap_.erase(iter);
272 }
273 HILOG_INFO("%{public}s done", __func__);
274 }
275
AddShareFormCallback(const std::shared_ptr<ShareFormCallBack> & shareFormCallback,int64_t requestCode)276 bool FormHostClient::AddShareFormCallback(const std::shared_ptr<ShareFormCallBack> &shareFormCallback,
277 int64_t requestCode)
278 {
279 HILOG_DEBUG("%{public}s called.", __func__);
280 std::lock_guard<std::mutex> lock(shareFormCallbackMutex_);
281 auto iter = shareFormCallbackMap_.find(requestCode);
282 if (iter == shareFormCallbackMap_.end()) {
283 shareFormCallbackMap_.emplace(requestCode, shareFormCallback);
284 }
285 HILOG_DEBUG("%{public}s done.", __func__);
286 return true;
287 }
288
OnShareFormResponse(int64_t requestCode,int32_t result)289 void FormHostClient::OnShareFormResponse(int64_t requestCode, int32_t result)
290 {
291 HILOG_DEBUG("%{public}s result:%{public}d.", __func__, result);
292 std::lock_guard<std::mutex> lock(shareFormCallbackMutex_);
293 auto iter = shareFormCallbackMap_.find(requestCode);
294 if (iter == shareFormCallbackMap_.end()) {
295 HILOG_DEBUG("share form callback not found");
296 return;
297 }
298
299 if (iter->second) {
300 iter->second->ProcessShareFormResponse(result);
301 }
302 shareFormCallbackMap_.erase(requestCode);
303 HILOG_DEBUG("%{public}s done", __func__);
304 }
305
OnError(int32_t errorCode,const std::string & errorMsg)306 void FormHostClient::OnError(int32_t errorCode, const std::string &errorMsg)
307 {
308 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
309 HILOG_ERROR("Receive error form FMS, errorCode: %{public}d, errorMsg: %{public}s.", errorCode, errorMsg.c_str());
310 std::lock_guard<std::mutex> lock(callbackMutex_);
311 for (auto formIdIter = etsFormIds_.begin(); formIdIter != etsFormIds_.end();) {
312 int64_t formId = *formIdIter;
313 auto callbackMapIter = formCallbackMap_.find(formId);
314 if (callbackMapIter == formCallbackMap_.end()) {
315 HILOG_ERROR("Can not find form: %{public}" PRId64 " in formCallbackMap, remove it.", formId);
316 formIdIter = etsFormIds_.erase(formIdIter);
317 continue;
318 }
319 ++formIdIter;
320
321 const std::set<std::shared_ptr<FormCallbackInterface>> &callbackSet = callbackMapIter->second;
322 HILOG_DEBUG("callbackSet.size: %{public}zu", callbackSet.size());
323 for (const auto &callback : callbackSet) {
324 if (callback == nullptr) {
325 HILOG_ERROR("FormCallback is nullptr.");
326 continue;
327 }
328 callback->OnError(errorCode, errorMsg);
329 }
330 }
331 }
332
RemoveShareFormCallback(int64_t requestCode)333 void FormHostClient::RemoveShareFormCallback(int64_t requestCode)
334 {
335 HILOG_DEBUG("%{public}s called", __func__);
336 std::lock_guard<std::mutex> lock(shareFormCallbackMutex_);
337 auto iter = shareFormCallbackMap_.find(requestCode);
338 if (iter != shareFormCallbackMap_.end()) {
339 shareFormCallbackMap_.erase(requestCode);
340 }
341 HILOG_INFO("%{public}s end.", __func__);
342 }
343
UpdateForm(const FormJsInfo & formJsInfo)344 void FormHostClient::UpdateForm(const FormJsInfo &formJsInfo)
345 {
346 HILOG_DEBUG("%{public}s called, image number is %{public}zu.", __func__, formJsInfo.imageDataMap.size());
347 int64_t formId = formJsInfo.formId;
348 if (formId < 0) {
349 HILOG_ERROR("%{public}s error, the passed form id can't be negative.", __func__);
350 return;
351 }
352 std::lock_guard<std::mutex> lock(callbackMutex_);
353 auto iter = formCallbackMap_.find(formId);
354 if (iter == formCallbackMap_.end()) {
355 HILOG_ERROR("%{public}s error, not find formId:%{public}s.", __func__, std::to_string(formId).c_str());
356 return;
357 }
358 for (const auto &callback : iter->second) {
359 HILOG_DEBUG("%{public}s, formId: %{public}" PRId64 ", jspath: %{public}s, data: %{private}s",
360 __func__, formId, formJsInfo.jsFormCodePath.c_str(), formJsInfo.formData.c_str());
361 callback->ProcessFormUpdate(formJsInfo);
362 }
363 }
364 } // namespace AppExecFwk
365 } // namespace OHOS
366