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