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 "data_center/form_data_proxy_record.h"
17
18 #include <cstddef>
19 #include <string>
20 #include <vector>
21
22 #include "fms_log_wrapper.h"
23 #include "bms_mgr/form_bms_helper.h"
24 #include "data_center/form_data_mgr.h"
25 #include "form_mgr/form_mgr_adapter.h"
26 #include "form_mgr_errors.h"
27 #include "form_provider/form_provider_mgr.h"
28 #include "common/util/form_util.h"
29 #include "ipc_skeleton.h"
30 #include "accesstoken_kit.h"
31 #include "common/event/form_event_report.h"
32 #include "form_mgr/form_mgr_queue.h"
33
34 namespace OHOS {
35 namespace AppExecFwk {
36 namespace {
37 const std::string KEY_DELIMITER = "?"; // the delimiter between key and uid
38 } // namespace
39
40 class PermissionCustomizeListener : public Security::AccessToken::PermStateChangeCallbackCustomize {
41 public:
42 std::weak_ptr<FormDataProxyRecord> formDataProxyRecord_;
PermissionCustomizeListener(const Security::AccessToken::PermStateChangeScope & scopeInfo,std::weak_ptr<FormDataProxyRecord> formDataProxyRecord)43 PermissionCustomizeListener(const Security::AccessToken::PermStateChangeScope &scopeInfo,
44 std::weak_ptr<FormDataProxyRecord> formDataProxyRecord)
45 : Security::AccessToken::PermStateChangeCallbackCustomize(scopeInfo)
46 {
47 formDataProxyRecord_ = formDataProxyRecord;
48 }
49
PermStateChangeCallback(Security::AccessToken::PermStateChangeInfo & result)50 virtual void PermStateChangeCallback(Security::AccessToken::PermStateChangeInfo& result)
51 {
52 HILOG_INFO("PermStateChangeCallback type:%{public}d, permissionName:%{public}s",
53 result.permStateChangeType, result.permissionName.c_str());
54 auto formDataProxyRecord = formDataProxyRecord_.lock();
55 if (formDataProxyRecord == nullptr) {
56 HILOG_INFO("null formDataPrxyRecord");
57 return;
58 }
59 formDataProxyRecord->PermStateChangeCallback(result.permStateChangeType, result.permissionName);
60 }
61 };
62
PermStateChangeCallback(const int32_t permStateChangeType,const std::string permissionName)63 void FormDataProxyRecord::PermStateChangeCallback(const int32_t permStateChangeType, const std::string permissionName)
64 {
65 HILOG_INFO("Permission has been changed, form id:%{public}" PRId64 ", permission name:%{public}s", formId_,
66 permissionName.c_str());
67 auto search = formDataPermissionProxyMap_.find(permissionName);
68 if (search == formDataPermissionProxyMap_.end()) {
69 HILOG_ERROR("no permission data proxy, permissionName :%{public}s", permissionName.c_str());
70 return;
71 }
72 std::vector<FormDataProxy> formDataProxies = search->second;
73 std::vector<FormDataProxy> subscribeFormDataProxies;
74 std::vector<FormDataProxy> unSubscribeFormDataProxies;
75 for (const auto &formDataProxy : formDataProxies) {
76 GetSubscribeFormDataProxies(formDataProxy, subscribeFormDataProxies, unSubscribeFormDataProxies);
77 }
78
79 bool isAuthorized = permStateChangeType == PERMISSION_GRANTED_OPER;
80 SubscribeMap rdbSubscribeMap;
81 SubscribeMap publishSubscribeMap;
82 if (isAuthorized) {
83 if (!subscribeFormDataProxies.empty()) {
84 SubscribeFormData(subscribeFormDataProxies, rdbSubscribeMap, publishSubscribeMap);
85 }
86 } else {
87 if (!unSubscribeFormDataProxies.empty()) {
88 ParseFormDataProxies(unSubscribeFormDataProxies, rdbSubscribeMap, publishSubscribeMap);
89 UnsubscribeFormData(rdbSubscribeMap, publishSubscribeMap);
90 }
91 }
92 Want newWant(wantCache_);
93 newWant.SetParam(Constants::FORM_PERMISSION_NAME_KEY, permissionName);
94 newWant.SetParam(Constants::FORM_PERMISSION_GRANTED_KEY, isAuthorized);
95 if (FormProviderMgr::GetInstance().ConnectAmsForRefreshPermission(formId_, newWant) != ERR_OK) {
96 HILOG_ERROR(
97 "ConnectAmsForRefreshPermission failed, permission name:%{public}s, isAuthorized:%{public}d",
98 permissionName.c_str(), isAuthorized);
99 return;
100 }
101 }
102
SetWant(const AAFwk::Want & want)103 void FormDataProxyRecord::SetWant(const AAFwk::Want &want)
104 {
105 wantCache_ = want;
106 }
107
GetSubscribeFormDataProxies(const FormDataProxy formDataProxy,std::vector<FormDataProxy> & subscribeFormDataProxies,std::vector<FormDataProxy> & unSubscribeFormDataProxies)108 void FormDataProxyRecord::GetSubscribeFormDataProxies(const FormDataProxy formDataProxy,
109 std::vector<FormDataProxy> &subscribeFormDataProxies, std::vector<FormDataProxy> &unSubscribeFormDataProxies)
110 {
111 std::string userId = std::to_string(FormUtil::GetCurrentAccountId());
112 std::string token = std::to_string(tokenId_);
113 std::string uri = formDataProxy.key + "?" + "user=" + userId + "&srcToken=" + token +
114 "&dstBundleName=" + bundleName_;
115 HILOG_INFO("get sub data, uri:%{public}s, formId_:%{public}" PRId64, uri.c_str(), formId_);
116 auto rdbSubscribeResult = rdbSubscribeResultMap_.find(uri);
117 if (rdbSubscribeResult != rdbSubscribeResultMap_.end()) {
118 int64_t subscriberId = formId_;
119 if (!FormUtil::ConvertStringToInt64(formDataProxy.subscribeId, subscriberId)) {
120 HILOG_WARN("Convert string subscribe[%{public}s] to int64 failed, change to default value "
121 "formId:%{public}" PRId64, formDataProxy.subscribeId.c_str(), formId_);
122 }
123 auto subscribeResultRecord = rdbSubscribeResult->second.find(subscriberId);
124 if (subscribeResultRecord != rdbSubscribeResult->second.end()) {
125 if (subscribeResultRecord->second.ret != 0) {
126 subscribeFormDataProxies.emplace_back(formDataProxy);
127 } else {
128 unSubscribeFormDataProxies.emplace_back(formDataProxy);
129 }
130 }
131 } else {
132 subscribeFormDataProxies.emplace_back(formDataProxy);
133 }
134 }
135
UnRegisterPermissionListener()136 void FormDataProxyRecord::UnRegisterPermissionListener()
137 {
138 if (callbackPtr_ != nullptr) {
139 int32_t accessTokenKit = Security::AccessToken::AccessTokenKit::UnRegisterPermStateChangeCallback(callbackPtr_);
140 callbackPtr_ = nullptr;
141 }
142 }
143
RegisterPermissionListener(const std::vector<FormDataProxy> & formDataProxies)144 void FormDataProxyRecord::RegisterPermissionListener(const std::vector<FormDataProxy> &formDataProxies)
145 {
146 std::vector<ProxyData> proxyData;
147 std::vector<std::string> permList;
148 FormBmsHelper::GetInstance().GetAllProxyDataInfos(FormUtil::GetCurrentAccountId(), proxyData);
149 if (proxyData.empty() || !formDataPermissionProxyMap_.empty()) {
150 return;
151 }
152 for (const auto &formDataProxy : formDataProxies) {
153 for (const auto &data : proxyData) {
154 if (formDataProxy.key != data.uri) {
155 continue;
156 }
157 auto search = formDataPermissionProxyMap_.find(data.requiredReadPermission);
158 std::vector<FormDataProxy> proxies;
159 if (search != formDataPermissionProxyMap_.end()) {
160 proxies = search->second;
161 }
162 permList.emplace_back(data.requiredReadPermission);
163 proxies.emplace_back(formDataProxy);
164 formDataPermissionProxyMap_[data.requiredReadPermission] = proxies;
165 break;
166 }
167 }
168 std::string callingIdentity = IPCSkeleton::ResetCallingIdentity();
169 Security::AccessToken::PermStateChangeScope scopeInfo;
170 scopeInfo.permList = {permList};
171 scopeInfo.tokenIDs = {tokenId_};
172 callbackPtr_ = std::make_shared<PermissionCustomizeListener>(scopeInfo, weak_from_this());
173 int32_t accessTokenKit = Security::AccessToken::AccessTokenKit::RegisterPermStateChangeCallback(callbackPtr_);
174 IPCSkeleton::SetCallingIdentity(callingIdentity);
175 HILOG_INFO("formId:%{public}" PRId64, formId_);
176 if (accessTokenKit != 0) {
177 formDataPermissionProxyMap_.clear();
178 }
179 }
180
181
OnRdbDataChange(const DataShare::RdbChangeNode & changeNode)182 void FormDataProxyRecord::OnRdbDataChange(const DataShare::RdbChangeNode &changeNode)
183 {
184 HILOG_INFO("rdb change. data size is %{public}zu", changeNode.data_.size());
185 if (changeNode.data_.size() == 0) {
186 return;
187 }
188 std::function<void()> taskFunc = [weak = weak_from_this(), data = changeNode.data_]() {
189 auto formDataRecord = weak.lock();
190 if (formDataRecord == nullptr) {
191 HILOG_ERROR("null formDataRecord.");
192 return;
193 }
194 formDataRecord->UpdateRdbDataForm(data);
195 };
196 if (!FormMgrQueue::GetInstance().ScheduleTask(0, taskFunc)) {
197 HILOG_ERROR("fail UpdateRdbDataForm.");
198 }
199 }
200
OnPublishedDataChange(const DataShare::PublishedDataChangeNode & changeNode)201 void FormDataProxyRecord::OnPublishedDataChange(const DataShare::PublishedDataChangeNode &changeNode)
202 {
203 HILOG_DEBUG("on published data change. data size is %{public}zu", changeNode.datas_.size());
204 UpdatePublishedDataForm(changeNode.datas_);
205 }
206
FormDataProxyRecord(int64_t formId,const std::string & bundleName,FormType uiSyntax,uint32_t tokenId,int32_t uid)207 FormDataProxyRecord::FormDataProxyRecord(int64_t formId, const std::string &bundleName, FormType uiSyntax,
208 uint32_t tokenId, int32_t uid) : formId_(formId), bundleName_(bundleName), uiSyntax_(uiSyntax),
209 tokenId_(tokenId), uid_(uid)
210 {
211 HILOG_INFO("create formId:%{public}" PRId64 ", bundleName:%{public}s", formId, bundleName.c_str());
212 std::string uri = "datashareproxy://" + bundleName;
213 DataShare::CreateOptions options;
214 options.isProxy_ = true;
215 dataShareHelper_ = DataShare::DataShareHelper::Creator(uri, options);
216 }
217
~FormDataProxyRecord()218 FormDataProxyRecord::~FormDataProxyRecord()
219 {
220 HILOG_INFO("destroy formId:%{public}" PRId64 ", bundleName:%{public}s", formId_, bundleName_.c_str());
221 UnRegisterPermissionListener();
222 if (dataShareHelper_ != nullptr) {
223 dataShareHelper_->Release();
224 }
225 }
226
SubscribeFormData(const std::vector<FormDataProxy> & formDataProxies)227 ErrCode FormDataProxyRecord::SubscribeFormData(const std::vector<FormDataProxy> &formDataProxies)
228 {
229 RegisterPermissionListener(formDataProxies);
230 return SubscribeFormData(formDataProxies, rdbSubscribeMap_, publishSubscribeMap_);
231 }
232
SubscribeFormData(const std::vector<FormDataProxy> & formDataProxies,SubscribeMap & rdbSubscribeMap,SubscribeMap & publishSubscribeMap)233 ErrCode FormDataProxyRecord::SubscribeFormData(const std::vector<FormDataProxy> &formDataProxies,
234 SubscribeMap &rdbSubscribeMap, SubscribeMap &publishSubscribeMap)
235 {
236 HILOG_INFO("subscribe form data, formDataProxies size:%{public}zu", formDataProxies.size());
237 ParseFormDataProxies(formDataProxies, rdbSubscribeMap, publishSubscribeMap);
238 ErrCode ret = ERR_OK;
239 ret = SubscribeRdbFormData(rdbSubscribeMap);
240 if (ret != ERR_OK) {
241 HILOG_ERROR("subscribe rdb form data failed");
242 return ret;
243 }
244 ret = SubscribePublishFormData(publishSubscribeMap);
245 if (ret != ERR_OK) {
246 HILOG_ERROR("subscribe publish form data failed");
247 return ret;
248 }
249 return ret;
250 }
251
SubscribeRdbFormData(const SubscribeMap & rdbSubscribeMap)252 ErrCode FormDataProxyRecord::SubscribeRdbFormData(const SubscribeMap &rdbSubscribeMap)
253 {
254 HILOG_INFO("SubscribeRdbFormData");
255 if (dataShareHelper_ == nullptr) {
256 HILOG_ERROR("null dataShareHelper");
257 return ERR_APPEXECFWK_FORM_INVALID_PARAM;
258 }
259
260 if (rdbSubscribeMap.empty()) {
261 HILOG_ERROR("empty rdbSubscribeMap");
262 return ERR_OK;
263 }
264
265 std::vector<FormDataProxyRequest> formDataProxyRequests;
266 ConvertSubscribeMapToRequests(rdbSubscribeMap, formDataProxyRequests);
267
268 std::weak_ptr<FormDataProxyRecord> weak(shared_from_this());
269 auto rdbTask = [weak](const DataShare::RdbChangeNode &changeNode) {
270 auto formDataRecord = weak.lock();
271 if (formDataRecord == nullptr) {
272 HILOG_ERROR("null formDataRecord");
273 return;
274 }
275 formDataRecord->OnRdbDataChange(changeNode);
276 };
277 for (const auto &search : formDataProxyRequests) {
278 DataShare::TemplateId templateId;
279 templateId.subscriberId_ = search.subscribeId;
280 templateId.bundleName_ = bundleName_;
281 auto ret = dataShareHelper_->SubscribeRdbData(search.uris, templateId, rdbTask);
282 uint32_t failNum = 0;
283 for (const auto &iter : ret) {
284 SubscribeResultRecord record{iter.key_, search.subscribeId, iter.errCode_, false, 0};
285 AddSubscribeResultRecord(record, true);
286 if (iter.errCode_ != 0) {
287 HILOG_ERROR("subscribe rdb data failed. uri:%{public}s, errCode:%{public}d",
288 iter.key_.c_str(), iter.errCode_);
289 failNum++;
290 }
291 }
292 HILOG_INFO("subscribe rdb data. subscribeId:%{public}" PRId64 ", failNum:%{public}d, totalNum:%{public}zu",
293 search.subscribeId, failNum, search.uris.size());
294 }
295
296 return ERR_OK;
297 }
298
SubscribePublishFormData(const SubscribeMap & publishSubscribeMap)299 ErrCode FormDataProxyRecord::SubscribePublishFormData(const SubscribeMap &publishSubscribeMap)
300 {
301 HILOG_INFO("SubscribePublishFormData");
302 if (dataShareHelper_ == nullptr) {
303 HILOG_ERROR("null dataShareHelper");
304 return ERR_APPEXECFWK_FORM_INVALID_PARAM;
305 }
306
307 if (publishSubscribeMap.empty()) {
308 HILOG_ERROR("null publishSubscribeMap");
309 return ERR_OK;
310 }
311
312 std::vector<FormDataProxyRequest> formDataProxyRequests;
313 ConvertSubscribeMapToRequests(publishSubscribeMap, formDataProxyRequests);
314
315 std::weak_ptr<FormDataProxyRecord> weak(shared_from_this());
316 auto publishedTask = [weak](const DataShare::PublishedDataChangeNode &changeNode) {
317 auto formDataRecord = weak.lock();
318 if (formDataRecord == nullptr) {
319 HILOG_ERROR("null formDataRecord");
320 return;
321 }
322 formDataRecord->OnPublishedDataChange(changeNode);
323 };
324 for (const auto &search : formDataProxyRequests) {
325 auto ret = dataShareHelper_->SubscribePublishedData(search.uris, search.subscribeId, publishedTask);
326 uint32_t failNum = 0;
327 for (const auto &iter : ret) {
328 SubscribeResultRecord record{iter.key_, search.subscribeId, iter.errCode_, false, 0};
329 AddSubscribeResultRecord(record, false);
330 if (iter.errCode_ != 0) {
331 HILOG_ERROR("subscribe published data failed. uri:%{public}s, errCode:%{public}d",
332 iter.key_.c_str(), iter.errCode_);
333 failNum++;
334 }
335 }
336 HILOG_INFO("subscribe published data. subscribeId:%{public}" PRId64 ", failNum:%{public}d, "
337 "totalNum:%{public}zu", search.subscribeId, failNum, search.uris.size());
338 }
339
340 return ERR_OK;
341 }
342
UnsubscribeFormData()343 ErrCode FormDataProxyRecord::UnsubscribeFormData()
344 {
345 return UnsubscribeFormData(rdbSubscribeMap_, publishSubscribeMap_);
346 }
347
UnsubscribeFormData(SubscribeMap & rdbSubscribeMap,SubscribeMap & publishSubscribeMap)348 ErrCode FormDataProxyRecord::UnsubscribeFormData(SubscribeMap &rdbSubscribeMap, SubscribeMap &publishSubscribeMap)
349 {
350 if (dataShareHelper_ == nullptr) {
351 HILOG_ERROR("null dataShareHelper");
352 return ERR_APPEXECFWK_FORM_INVALID_PARAM;
353 }
354
355 std::vector<FormDataProxyRequest> rdbRequests;
356 ConvertSubscribeMapToRequests(rdbSubscribeMap, rdbRequests);
357 for (const auto &search : rdbRequests) {
358 DataShare::TemplateId templateId;
359 templateId.subscriberId_ = search.subscribeId;
360 templateId.bundleName_ = bundleName_;
361 dataShareHelper_->UnsubscribeRdbData(search.uris, templateId);
362 for (const auto &uri : search.uris) {
363 RemoveSubscribeResultRecord(uri, search.subscribeId, true);
364 }
365 HILOG_INFO("Unsubscribe rdb. subscribeId:%{public}" PRId64 ", totalNum:%{public}zu, bundleName_:%{public}s, "
366 "formId_:%{public}" PRId64, search.subscribeId, search.uris.size(), bundleName_.c_str(), formId_);
367 }
368 rdbSubscribeMap.clear();
369
370 std::vector<FormDataProxyRequest> publishRequests;
371 ConvertSubscribeMapToRequests(publishSubscribeMap, publishRequests);
372 for (const auto &search : publishRequests) {
373 dataShareHelper_->UnsubscribePublishedData(search.uris, search.subscribeId);
374 for (const auto &uri : search.uris) {
375 RemoveSubscribeResultRecord(uri, search.subscribeId, false);
376 }
377 HILOG_INFO("Unsubscribe publish. subscribeId:%{public}" PRId64 ", totalNum:%{public}zu, "
378 "formId_:%{public}" PRId64, search.subscribeId, search.uris.size(), formId_);
379 }
380 publishSubscribeMap.clear();
381 return ERR_OK;
382 }
383
ParseFormDataProxies(const std::vector<FormDataProxy> & formDataProxies,SubscribeMap & rdbSubscribeMap,SubscribeMap & publishSubscribeMap)384 void FormDataProxyRecord::ParseFormDataProxies(const std::vector<FormDataProxy> &formDataProxies,
385 SubscribeMap &rdbSubscribeMap, SubscribeMap &publishSubscribeMap)
386 {
387 std::vector<ProxyData> proxyData;
388 FormBmsHelper::GetInstance().GetAllProxyDataInfos(FormUtil::GetCurrentAccountId(), proxyData);
389 HILOG_INFO("size:%{public}zu", proxyData.size());
390 std::unordered_set<std::string> expectedKeys;
391 for (auto &data : proxyData) {
392 expectedKeys.emplace(data.uri);
393 }
394
395 HILOG_INFO("subscribe rdb data");
396 ParseFormDataProxiesIntoSubscribeMapWithExpectedKeys(formDataProxies, expectedKeys, true, rdbSubscribeMap);
397 HILOG_INFO("subscribe publish data");
398 ParseFormDataProxiesIntoSubscribeMapWithExpectedKeys(formDataProxies, expectedKeys, false, publishSubscribeMap);
399 }
400
ParseFormDataProxiesIntoSubscribeMapWithExpectedKeys(const std::vector<FormDataProxy> & formDataProxies,const std::unordered_set<std::string> & expectedKeys,bool keyCheckingNeeded,SubscribeMap & subscribeMap)401 void FormDataProxyRecord::ParseFormDataProxiesIntoSubscribeMapWithExpectedKeys(
402 const std::vector<FormDataProxy> &formDataProxies, const std::unordered_set<std::string> &expectedKeys,
403 bool keyCheckingNeeded, SubscribeMap &subscribeMap)
404 {
405 subscribeMap.clear();
406 for (const auto &formDataProxy : formDataProxies) {
407 if (keyCheckingNeeded && expectedKeys.find(formDataProxy.key) == expectedKeys.end()) {
408 continue;
409 }
410 auto subscribe = formDataProxy.subscribeId.empty() ? std::to_string(formId_) : formDataProxy.subscribeId;
411 auto it = subscribeMap.find(formDataProxy.key);
412 if (it == subscribeMap.end()) {
413 std::unordered_set<std::string> subscribeIds;
414 subscribeIds.emplace(subscribe);
415 subscribeMap.emplace(formDataProxy.key, subscribeIds);
416 } else {
417 it->second.emplace(subscribe);
418 }
419 HILOG_INFO("parse subscribe, uri:%{public}s, subscribeId:%{public}s, rdb:%{public}d formId_:%{public}" PRId64,
420 formDataProxy.key.c_str(), subscribe.c_str(), keyCheckingNeeded, formId_);
421 }
422 }
423
ConvertSubscribeMapToRequests(const SubscribeMap & subscribeMap,std::vector<FormDataProxyRequest> & formDataProxyRequests)424 void FormDataProxyRecord::ConvertSubscribeMapToRequests(
425 const SubscribeMap &subscribeMap, std::vector<FormDataProxyRequest> &formDataProxyRequests)
426 {
427 formDataProxyRequests.clear();
428 std::string userId = std::to_string(FormUtil::GetCurrentAccountId());
429 std::string token = std::to_string(tokenId_);
430 std::unordered_map<int64_t, std::vector<std::string>> subscribeId2UrisMap;
431
432 for (const auto &record : subscribeMap) {
433 const auto &key = record.first;
434 for (const auto &subscribe : record.second) {
435 int64_t subscriberId = formId_;
436 if (!FormUtil::ConvertStringToInt64(subscribe, subscriberId)) {
437 HILOG_WARN("Convert string subscribe[%{public}s] to int64 failed, change to default value "
438 "formId:%{public}" PRId64, subscribe.c_str(), formId_);
439 }
440
441 std::string uri = key + "?" + "user=" + userId + "&srcToken=" + token + "&dstBundleName=" + bundleName_;
442 HILOG_INFO("Convert data, uri:%{public}s, subscriberId:%{public}" PRId64, uri.c_str(), subscriberId);
443 auto it = subscribeId2UrisMap.find(subscriberId);
444 if (it == subscribeId2UrisMap.end()) {
445 std::vector<std::string> uris;
446 uris.push_back(uri);
447 subscribeId2UrisMap.emplace(subscriberId, uris);
448 } else {
449 it->second.push_back(uri);
450 }
451 }
452 }
453
454 for (auto &record : subscribeId2UrisMap) {
455 FormDataProxyRequest request{record.first, std::move(record.second)};
456 formDataProxyRequests.push_back(request);
457 }
458 }
459
UpdatePublishedDataForm(const std::vector<DataShare::PublishedDataItem> & data)460 void FormDataProxyRecord::UpdatePublishedDataForm(const std::vector<DataShare::PublishedDataItem> &data)
461 {
462 std::map<std::string, std::pair<sptr<FormAshmem>, int32_t>> imageDataMap;
463 nlohmann::json object;
464 std::string formDataKeysStr = "";
465 for (const auto& iter : data) {
466 if (iter.key_.empty()) {
467 HILOG_ERROR("empty key");
468 continue;
469 }
470 if (iter.IsAshmem()) {
471 PrepareImageData(iter, object, imageDataMap);
472 } else {
473 auto value = std::get<std::string>(iter.value_);
474 nlohmann::json dataObject = nlohmann::json::parse(value, nullptr, false);
475 if (dataObject.is_discarded()) {
476 HILOG_ERROR("fail parse data:%{public}s", value.c_str());
477 continue;
478 }
479 object[iter.key_] = dataObject;
480 std::string newKeyStr = formDataKeysStr.empty() ? iter.key_ : (", " + iter.key_);
481 formDataKeysStr += newKeyStr;
482 }
483 }
484 std::string formDataStr = object.empty() ? "" : object.dump();
485 HILOG_INFO("formId:%{public}" PRId64 " update published data. formDataStr[len:%{public}zu], "
486 "formDataKeysStr:%{public}s, imageDataMap size:%{public}zu", formId_, formDataStr.length(),
487 formDataKeysStr.c_str(), imageDataMap.size());
488
489 FormProviderData formProviderData;
490 formProviderData.SetDataString(formDataStr);
491 if (!imageDataMap.empty()) {
492 formProviderData.SetImageDataState(FormProviderData::IMAGE_DATA_STATE_ADDED);
493 formProviderData.SetImageDataMap(imageDataMap);
494 }
495 FormDataMgr::GetInstance().SetDataProxyUpdate(formId_);
496 auto ret = FormMgrAdapter::GetInstance().UpdateForm(formId_, uid_, formProviderData);
497 NewFormEventInfo eventInfo;
498 eventInfo.formId = formId_;
499 eventInfo.bundleName = bundleName_;
500 FormEventReport::SendFourthFormEvent(FormEventName::PROXY_UPDATE_FORM,
501 HiSysEventType::STATISTIC, eventInfo, wantCache_);
502 if (ret == ERR_OK && receivedDataCount_ < INT32_MAX) {
503 receivedDataCount_ += 1;
504 }
505 }
506
UpdateRdbDataForm(const std::vector<std::string> & data)507 void FormDataProxyRecord::UpdateRdbDataForm(const std::vector<std::string> &data)
508 {
509 nlohmann::json object;
510 for (const auto& iter : data) {
511 HILOG_DEBUG("iter: %{private}s.", iter.c_str());
512 nlohmann::json dataObject = nlohmann::json::parse(iter, nullptr, false);
513 if (dataObject.is_discarded()) {
514 HILOG_ERROR("fail parse data:%{public}s", iter.c_str());
515 continue;
516 }
517 object.merge_patch(dataObject);
518 }
519
520 std::string formDataStr = object.empty() ? "" : object.dump();
521 HILOG_INFO("formId:%{public}" PRId64 " update rdb data. formDataStr[len:%{public}zu].",
522 formId_, formDataStr.length());
523
524 FormProviderData formProviderData;
525 formProviderData.SetDataString(formDataStr);
526
527 FormDataMgr::GetInstance().SetDataProxyUpdate(formId_);
528 auto ret = FormMgrAdapter::GetInstance().UpdateForm(formId_, uid_, formProviderData);
529 if (ret == ERR_OK && receivedDataCount_ < INT32_MAX) {
530 receivedDataCount_ += 1;
531 }
532 }
533
UpdateSubscribeFormData(const std::vector<FormDataProxy> & formDataProxies)534 void FormDataProxyRecord::UpdateSubscribeFormData(const std::vector<FormDataProxy> &formDataProxies)
535 {
536 HILOG_INFO("call");
537 SubscribeMap originRdbMap;
538 SubscribeMap newRdbMap;
539 SubscribeMap originPublishMap;
540 SubscribeMap newPublishMap;
541 UpdateSubscribeMap(formDataProxies, originRdbMap, newRdbMap, originPublishMap, newPublishMap);
542 UnsubscribeFormData(originRdbMap, originPublishMap);
543 SubscribeRdbFormData(newRdbMap);
544 SubscribePublishFormData(newPublishMap);
545 }
546
UpdateSubscribeMap(const std::vector<FormDataProxy> & formDataProxies,SubscribeMap & originRdbMap,SubscribeMap & newRdbMap,SubscribeMap & originPublishMap,SubscribeMap & newPublishMap)547 void FormDataProxyRecord::UpdateSubscribeMap(const std::vector<FormDataProxy> &formDataProxies,
548 SubscribeMap &originRdbMap, SubscribeMap &newRdbMap, SubscribeMap &originPublishMap, SubscribeMap &newPublishMap)
549 {
550 SubscribeMap updateMap;
551 std::unordered_set<std::string> expectedKeys;
552 ParseFormDataProxiesIntoSubscribeMapWithExpectedKeys(formDataProxies, expectedKeys, false, updateMap);
553 for (const auto &record : updateMap) {
554 const auto &key = record.first;
555 const auto &newSubscribeIds = record.second;
556 auto it = rdbSubscribeMap_.find(key);
557 if (it != rdbSubscribeMap_.end()) {
558 originRdbMap[key] = it->second;
559 newRdbMap[key] = newSubscribeIds;
560 rdbSubscribeMap_[key] = newSubscribeIds;
561 }
562 it = publishSubscribeMap_.find(key);
563 if (it != publishSubscribeMap_.end()) {
564 originPublishMap[key] = it->second;
565 newPublishMap[key] = newSubscribeIds;
566 publishSubscribeMap_[key] = newSubscribeIds;
567 }
568 }
569 }
570
EnableSubscribeFormData()571 void FormDataProxyRecord::EnableSubscribeFormData()
572 {
573 HILOG_INFO("enable subscribe form, formId:%{public}" PRId64 ", rdbSize:%{public}zu, publishSize:%{public}zu",
574 formId_, rdbSubscribeMap_.size(), publishSubscribeMap_.size());
575 SetRdbSubsState(rdbSubscribeMap_, true);
576 SetPublishSubsState(publishSubscribeMap_, true);
577 }
578
DisableSubscribeFormData()579 void FormDataProxyRecord::DisableSubscribeFormData()
580 {
581 HILOG_INFO("disable subscribe form, formId:%{public}" PRId64, formId_);
582 SetRdbSubsState(rdbSubscribeMap_, false);
583 SetPublishSubsState(publishSubscribeMap_, false);
584 }
585
RetryFailureSubscribes()586 void FormDataProxyRecord::RetryFailureSubscribes()
587 {
588 HILOG_INFO("formId:%{public}" PRId64, formId_);
589 if (dataShareHelper_ == nullptr) {
590 HILOG_ERROR("null dataShareHelper");
591 return;
592 }
593
594 for (auto& result : rdbSubscribeResultMap_) {
595 for (auto& records : result.second) {
596 auto& record = records.second;
597 RetryFailureRdbSubscribes(record);
598 }
599 }
600
601 for (auto& result : publishSubscribeResultMap_) {
602 for (auto& records : result.second) {
603 auto& record = records.second;
604 RetryFailurePublishedSubscribes(record);
605 }
606 }
607 }
608
GetFormSubscribeInfo(std::vector<std::string> & subscribedKeys,int32_t & count)609 void FormDataProxyRecord::GetFormSubscribeInfo(std::vector<std::string> &subscribedKeys, int32_t &count)
610 {
611 GetFormSubscribeKeys(subscribedKeys, true);
612 GetFormSubscribeKeys(subscribedKeys, false);
613 count = receivedDataCount_;
614 }
615
SetRdbSubsState(const SubscribeMap & rdbSubscribeMap,bool subsState)616 ErrCode FormDataProxyRecord::SetRdbSubsState(const SubscribeMap &rdbSubscribeMap, bool subsState)
617 {
618 if (dataShareHelper_ == nullptr) {
619 HILOG_ERROR("null dataShareHelper");
620 return ERR_APPEXECFWK_FORM_INVALID_PARAM;
621 }
622
623 if (rdbSubscribeMap.empty()) {
624 HILOG_DEBUG("empty rdbSubscribeMap");
625 return ERR_OK;
626 }
627
628 std::vector<FormDataProxyRequest> formDataProxyRequests;
629 ConvertSubscribeMapToRequests(rdbSubscribeMap, formDataProxyRequests);
630
631 for (const auto &search : formDataProxyRequests) {
632 DataShare::TemplateId templateId;
633 templateId.subscriberId_ = search.subscribeId;
634 templateId.bundleName_ = bundleName_;
635 std::vector<DataShare::OperationResult> ret;
636 if (subsState) {
637 ret = dataShareHelper_->EnableRdbSubs(search.uris, templateId);
638 } else {
639 ret = dataShareHelper_->DisableRdbSubs(search.uris, templateId);
640 }
641 uint32_t failNum = 0;
642 for (const auto &iter : ret) {
643 if (iter.errCode_ != 0) {
644 PrintSubscribeState(iter.key_, search.subscribeId, true);
645 failNum++;
646 }
647 }
648 HILOG_DEBUG("set rdb state. subscribeId:%{public}" PRId64 ", failNum:%{public}d, totalNum:%{public}zu",
649 search.subscribeId, failNum, search.uris.size());
650 }
651
652 return ERR_OK;
653 }
654
SetPublishSubsState(const SubscribeMap & publishSubscribeMap,bool subsState)655 ErrCode FormDataProxyRecord::SetPublishSubsState(const SubscribeMap &publishSubscribeMap,
656 bool subsState)
657 {
658 if (dataShareHelper_ == nullptr) {
659 HILOG_ERROR("null dataShareHelper");
660 return ERR_APPEXECFWK_FORM_INVALID_PARAM;
661 }
662
663 if (publishSubscribeMap.empty()) {
664 HILOG_DEBUG("null publishSubscribeMap");
665 return ERR_OK;
666 }
667
668 std::vector<FormDataProxyRequest> formDataProxyRequests;
669 ConvertSubscribeMapToRequests(publishSubscribeMap, formDataProxyRequests);
670
671 for (const auto &search : formDataProxyRequests) {
672 std::vector<DataShare::OperationResult> ret;
673 if (subsState) {
674 ret = dataShareHelper_->EnablePubSubs(search.uris, search.subscribeId);
675 } else {
676 ret = dataShareHelper_->DisablePubSubs(search.uris, search.subscribeId);
677 }
678 uint32_t failNum = 0;
679 for (const auto &iter : ret) {
680 if (iter.errCode_ != 0) {
681 PrintSubscribeState(iter.key_, search.subscribeId, false);
682 failNum++;
683 }
684 }
685 HILOG_DEBUG("set published state. subscribeId:%{public}" PRId64 ", failNum:%{public}d, totalNum:%{public}zu",
686 search.subscribeId, failNum, search.uris.size());
687 }
688
689 return ERR_OK;
690 }
691
692 /*
693 * we need to automatically produce image names due to differences in usage between image publishing and rendering
694 */
PrepareImageData(const DataShare::PublishedDataItem & data,nlohmann::json & jsonObj,std::map<std::string,std::pair<sptr<FormAshmem>,int32_t>> & imageDataMap)695 bool FormDataProxyRecord::PrepareImageData(const DataShare::PublishedDataItem &data, nlohmann::json &jsonObj,
696 std::map<std::string, std::pair<sptr<FormAshmem>, int32_t>> &imageDataMap)
697 {
698 auto node = std::get<DataShare::AshmemNode>(data.value_);
699 if (node.ashmem == nullptr) {
700 HILOG_ERROR("null node.ashmem");
701 return false;
702 }
703 sptr<FormAshmem> formAshmem = new (std::nothrow) FormAshmem();
704 if (formAshmem == nullptr) {
705 HILOG_ERROR("alloc shmem failed");
706 return false;
707 }
708 auto size = node.ashmem->GetAshmemSize();
709 auto imageName = data.key_ + std::to_string(FormUtil::GetCurrentNanosecond());
710 if (!formAshmem->WriteToAshmem(imageName, (char *)node.ashmem->ReadFromAshmem(size, 0), size)) {
711 HILOG_ERROR("write to shmem failed");
712 return false;
713 }
714
715 jsonObj[data.key_] = imageName;
716 if (uiSyntax_ == FormType::JS) {
717 jsonObj[data.key_] = "memory://" + imageName; // adapt memory image uri for js card
718 }
719
720 std::pair<sptr<FormAshmem>, int32_t> imageDataRecord = std::make_pair(formAshmem, sizeof(formAshmem));
721 imageDataMap[imageName] = imageDataRecord;
722 return true;
723 }
724
AddSubscribeResultRecord(SubscribeResultRecord record,bool isRdbType)725 void FormDataProxyRecord::AddSubscribeResultRecord(SubscribeResultRecord record, bool isRdbType)
726 {
727 std::map<std::string, std::map<int64_t, SubscribeResultRecord>>* resultMap =
728 isRdbType ? &rdbSubscribeResultMap_ : &publishSubscribeResultMap_;
729 auto mapIter = resultMap->find(record.uri);
730 if (mapIter == resultMap->end()) {
731 std::map<int64_t, SubscribeResultRecord> records;
732 records.emplace(record.subscribeId, record);
733 resultMap->emplace(record.uri, records);
734 } else {
735 mapIter->second[record.subscribeId] = record;
736 }
737 }
738
RemoveSubscribeResultRecord(const std::string & uri,int64_t subscribeId,bool isRdbType)739 void FormDataProxyRecord::RemoveSubscribeResultRecord(const std::string &uri, int64_t subscribeId, bool isRdbType)
740 {
741 std::map<std::string, std::map<int64_t, SubscribeResultRecord>>* resultMap =
742 isRdbType ? &rdbSubscribeResultMap_ : &publishSubscribeResultMap_;
743 auto mapIter = resultMap->find(uri);
744 if (mapIter == resultMap->end()) {
745 return;
746 }
747 auto it = mapIter->second.find(subscribeId);
748 if (it != mapIter->second.end()) {
749 mapIter->second.erase(it);
750 }
751 if (mapIter->second.empty()) {
752 resultMap->erase(mapIter);
753 }
754 }
755
PrintSubscribeState(const std::string & uri,int64_t subscribeId,bool isRdbType)756 void FormDataProxyRecord::PrintSubscribeState(const std::string &uri, int64_t subscribeId, bool isRdbType)
757 {
758 std::string type = isRdbType ? "rdb" : "published";
759 std::map<std::string, std::map<int64_t, SubscribeResultRecord>>* resultMap =
760 isRdbType ? &rdbSubscribeResultMap_ : &publishSubscribeResultMap_;
761 bool alreadySubscribed = true;
762 auto mapIter = resultMap->find(uri);
763 if (mapIter == resultMap->end()) {
764 alreadySubscribed = false;
765 } else {
766 auto it = mapIter->second.find(subscribeId);
767 if (it == mapIter->second.end()) {
768 alreadySubscribed = false;
769 } else {
770 HILOG_ERROR("subscribe state, type:%{public}s, uri:%{public}s, subscriberId:%{public}" PRId64 ", "
771 "ret:%{public}d, retry:%{public}s, retryRet:%{public}d", type.c_str(), uri.c_str(),
772 subscribeId, it->second.ret, (it->second.retry ? "yes" : "no"),
773 it->second.retryRet);
774 }
775 }
776 if (!alreadySubscribed) {
777 HILOG_ERROR("fail find subscribe record, type:%{public}s uri:%{public}s, subscriberId:%{public}" PRId64,
778 type.c_str(), uri.c_str(), subscribeId);
779 }
780 }
781
RetryFailureRdbSubscribes(SubscribeResultRecord & record)782 void FormDataProxyRecord::RetryFailureRdbSubscribes(SubscribeResultRecord &record)
783 {
784 // ok or already retry
785 if (record.ret == 0 || record.retry) {
786 return;
787 }
788
789 std::weak_ptr<FormDataProxyRecord> weak(shared_from_this());
790 auto rdbTask = [weak](const DataShare::RdbChangeNode &changeNode) {
791 auto formDataRecord = weak.lock();
792 if (formDataRecord == nullptr) {
793 HILOG_ERROR("null formDataRecord");
794 return;
795 }
796 formDataRecord->OnRdbDataChange(changeNode);
797 };
798
799 record.retry = true;
800 std::vector<std::string> uris{record.uri};
801 DataShare::TemplateId templateId;
802 templateId.subscriberId_ = record.subscribeId;
803 templateId.bundleName_ = bundleName_;
804 auto ret = dataShareHelper_->SubscribeRdbData(uris, templateId, rdbTask);
805 for (const auto &iter : ret) {
806 if (iter.errCode_ != 0) {
807 HILOG_ERROR("retry subscribe rdb data failed, uri:%{public}s, subscriberId:%{public}" PRId64 ", "
808 "errCode:%{public}d", iter.key_.c_str(), record.subscribeId, iter.errCode_);
809 } else {
810 HILOG_INFO("success, uri:%{public}s, subscriberId:%{public}" PRId64,
811 iter.key_.c_str(), record.subscribeId);
812 }
813 record.retryRet = iter.errCode_;
814 }
815 }
816
RetryFailurePublishedSubscribes(SubscribeResultRecord & record)817 void FormDataProxyRecord::RetryFailurePublishedSubscribes(SubscribeResultRecord &record)
818 {
819 // ok or already retry
820 if (record.ret == 0 || record.retry) {
821 return;
822 }
823
824 std::weak_ptr<FormDataProxyRecord> weak(shared_from_this());
825 auto publishedTask = [weak](const DataShare::PublishedDataChangeNode &changeNode) {
826 auto formDataRecord = weak.lock();
827 if (formDataRecord == nullptr) {
828 HILOG_ERROR("null formDataRecord");
829 return;
830 }
831 formDataRecord->OnPublishedDataChange(changeNode);
832 };
833
834 record.retry = true;
835 std::vector<std::string> uris{record.uri};
836 auto ret = dataShareHelper_->SubscribePublishedData(uris, record.subscribeId, publishedTask);
837 for (const auto &iter : ret) {
838 if (iter.errCode_ != 0) {
839 HILOG_ERROR("retry subscribe published data failed, uri:%{public}s, subscriberId:%{public}" PRId64 ", "
840 "errCode:%{public}d", iter.key_.c_str(), record.subscribeId, iter.errCode_);
841 } else {
842 HILOG_INFO("success, uri:%{public}s, subscriberId:%{public}" PRId64,
843 iter.key_.c_str(), record.subscribeId);
844 }
845 record.retryRet = iter.errCode_;
846 }
847 }
848
GetFormSubscribeKeys(std::vector<std::string> & subscribedKeys,bool isRdbType)849 void FormDataProxyRecord::GetFormSubscribeKeys(std::vector<std::string> &subscribedKeys, bool isRdbType)
850 {
851 auto resultMap = isRdbType ? rdbSubscribeResultMap_ : publishSubscribeResultMap_;
852 for (auto &result : resultMap) {
853 for (auto &records : result.second) {
854 auto &record = records.second;
855 if (record.ret != 0) {
856 continue;
857 }
858 auto uri = record.uri;
859 auto index = uri.find(KEY_DELIMITER);
860 if (index == std::string::npos) {
861 return;
862 }
863 auto subscribeKey = uri.substr(0, index);
864 auto search = std::find(subscribedKeys.begin(), subscribedKeys.end(), subscribeKey);
865 if (search == subscribedKeys.end()) {
866 subscribedKeys.emplace_back(subscribeKey);
867 }
868 }
869 }
870 }
871 } // namespace AppExecFwk
872 } // namespace OHOS