• 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 "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