1 /*
2 * Copyright (c) 2021 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 <cinttypes>
17
18 #include "appexecfwk_errors.h"
19 #include "form_bms_helper.h"
20 #include "form_data_mgr.h"
21 #include "form_db_cache.h"
22 #include "form_db_info.h"
23 #include "form_provider_mgr.h"
24 #include "hilog_wrapper.h"
25
26 namespace OHOS {
27 namespace AppExecFwk {
FormDbCache()28 FormDbCache::FormDbCache()
29 {
30 HILOG_INFO("FormDbCache is created");
31 dataStorage_ = std::make_shared<FormStorageMgr>();
32 formDBInfos_.clear();
33 }
34
~FormDbCache()35 FormDbCache::~FormDbCache()
36 {
37 HILOG_INFO("FormDbCache is destroyed");
38 }
39
40 /**
41 * @brief Load form data from DB to DbCache when starting.
42 * @return Void.
43 */
Start()44 void FormDbCache::Start()
45 {
46 HILOG_INFO("%{public}s called.", __func__);
47 std::lock_guard<std::mutex> lock(formDBInfosMutex_);
48 std::vector<InnerFormInfo> innerFormInfos;
49 innerFormInfos.clear();
50 if (dataStorage_->LoadFormData(innerFormInfos) != ERR_OK) {
51 HILOG_ERROR("%{public}s, LoadFormData failed.", __func__);
52 return;
53 }
54
55 for (unsigned int i = 0; i < innerFormInfos.size(); i++) {
56 FormDBInfo formDBInfo = innerFormInfos.at(i).GetFormDBInfo();
57 formDBInfos_.emplace_back(formDBInfo);
58 }
59 }
60
61 /**
62 * @brief Save or update form data to DbCache and DB.
63 * @param formDBInfo Form data.
64 * @return Returns ERR_OK on success, others on failure.
65 */
SaveFormInfo(const FormDBInfo & formDBInfo)66 ErrCode FormDbCache::SaveFormInfo(const FormDBInfo &formDBInfo)
67 {
68 HILOG_INFO("%{public}s called, formId:%{public}" PRId64 "", __func__, formDBInfo.formId);
69 std::lock_guard<std::mutex> lock(formDBInfosMutex_);
70 auto iter = find(formDBInfos_.begin(), formDBInfos_.end(), formDBInfo);
71 if (iter != formDBInfos_.end()) {
72 if (iter->Compare(formDBInfo) == false) {
73 HILOG_WARN("%{public}s, need update, formId[%{public}" PRId64 "].", __func__, formDBInfo.formId);
74 *iter = formDBInfo;
75 InnerFormInfo innerFormInfo(formDBInfo);
76 return dataStorage_->ModifyStorageFormInfo(innerFormInfo);
77 } else {
78 HILOG_WARN("%{public}s, already exist, formId[%{public}" PRId64 "].", __func__, formDBInfo.formId);
79 return ERR_OK;
80 }
81 } else {
82 formDBInfos_.emplace_back(formDBInfo);
83 InnerFormInfo innerFormInfo(formDBInfo);
84 return dataStorage_->SaveStorageFormInfo(innerFormInfo);
85 }
86 }
87
88 /**
89 * @brief Save or update form data to DbCache and DB.
90 * @param formDBInfo Form data.
91 * @return Returns ERR_OK on success, others on failure.(NoLock)
92 */
SaveFormInfoNolock(const FormDBInfo & formDBInfo)93 ErrCode FormDbCache::SaveFormInfoNolock(const FormDBInfo &formDBInfo)
94 {
95 HILOG_INFO("%{public}s called, formId:%{public}" PRId64 "", __func__, formDBInfo.formId);
96 auto iter = find(formDBInfos_.begin(), formDBInfos_.end(), formDBInfo);
97 if (iter != formDBInfos_.end()) {
98 if (iter->Compare(formDBInfo) == false) {
99 HILOG_WARN("%{public}s, need update, formId[%{public}" PRId64 "].", __func__, formDBInfo.formId);
100 *iter = formDBInfo;
101 InnerFormInfo innerFormInfo(formDBInfo);
102 return dataStorage_->ModifyStorageFormInfo(innerFormInfo);
103 } else {
104 HILOG_WARN("%{public}s, already exist, formId[%{public}" PRId64 "].", __func__, formDBInfo.formId);
105 return ERR_OK;
106 }
107 } else {
108 formDBInfos_.emplace_back(formDBInfo);
109 InnerFormInfo innerFormInfo(formDBInfo);
110 return dataStorage_->SaveStorageFormInfo(innerFormInfo);
111 }
112 }
113
114 /**
115 * @brief Delete form data in DbCache and DB with formId.
116 * @param formId form data Id.
117 * @return Returns ERR_OK on success, others on failure.
118 */
DeleteFormInfo(int64_t formId)119 ErrCode FormDbCache::DeleteFormInfo(int64_t formId)
120 {
121 std::lock_guard<std::mutex> lock(formDBInfosMutex_);
122 FormDBInfo tmpForm;
123 tmpForm.formId = formId;
124 auto iter = find(formDBInfos_.begin(), formDBInfos_.end(), tmpForm);
125 if (iter == formDBInfos_.end()) {
126 HILOG_WARN("%{public}s, not find formId[%{public}" PRId64 "]", __func__, formId);
127 } else {
128 formDBInfos_.erase(iter);
129 }
130 if (dataStorage_->DeleteStorageFormInfo(std::to_string(formId)) == ERR_OK) {
131 return ERR_OK;
132 } else {
133 return ERR_APPEXECFWK_FORM_COMMON_CODE;
134 }
135 }
136 /**
137 * @brief Delete form data in DbCache and DB with formId.
138 * @param formId form data Id.
139 * @param removedDBForms Removed db form infos
140 * @return Returns ERR_OK on success, others on failure.
141 */
DeleteFormInfoByBundleName(const std::string & bundleName,const int32_t userId,std::vector<FormDBInfo> & removedDBForms)142 ErrCode FormDbCache::DeleteFormInfoByBundleName(const std::string &bundleName, const int32_t userId,
143 std::vector<FormDBInfo> &removedDBForms)
144 {
145 std::lock_guard<std::mutex> lock(formDBInfosMutex_);
146 std::vector<FormDBInfo>::iterator itRecord;
147 for (itRecord = formDBInfos_.begin(); itRecord != formDBInfos_.end(); ) {
148 if ((bundleName == itRecord->bundleName) && (userId == itRecord->userId)) {
149 int64_t formId = itRecord->formId;
150 if (dataStorage_->DeleteStorageFormInfo(std::to_string(formId)) == ERR_OK) {
151 removedDBForms.emplace_back(*itRecord);
152 itRecord = formDBInfos_.erase(itRecord);
153 } else {
154 itRecord++;
155 }
156 } else {
157 itRecord++;
158 }
159 }
160 return ERR_OK;
161 }
162
163 /**
164 * @brief Get all form data from DbCache.
165 * @param formDBInfos Storage all DbCache.
166 * @return Void.
167 */
GetAllFormInfo(std::vector<FormDBInfo> & formDBInfos)168 void FormDbCache::GetAllFormInfo(std::vector<FormDBInfo> &formDBInfos)
169 {
170 HILOG_INFO("%{public}s called.", __func__);
171 std::lock_guard<std::mutex> lock(formDBInfosMutex_);
172 formDBInfos = formDBInfos_;
173 }
174
175 /**
176 * @brief Get record from DB cache with formId
177 * @param formId Form data Id
178 * @param record Form data
179 * @return Returns ERR_OK on success, others on failure.
180 */
GetDBRecord(const int64_t formId,FormRecord & record) const181 ErrCode FormDbCache::GetDBRecord(const int64_t formId, FormRecord &record) const
182 {
183 std::lock_guard<std::mutex> lock(formDBInfosMutex_);
184 for (const FormDBInfo &dbInfo : formDBInfos_) {
185 if (dbInfo.formId == formId) {
186 record.userId = dbInfo.userId;
187 record.formName = dbInfo.formName;
188 record.bundleName = dbInfo.bundleName;
189 record.moduleName = dbInfo.moduleName;
190 record.abilityName = dbInfo.abilityName;
191 record.formUserUids = dbInfo.formUserUids;
192 return ERR_OK;
193 }
194 }
195 HILOG_ERROR("%{public}s, not find formId[%{public}" PRId64 "]", __func__, formId);
196 return ERR_APPEXECFWK_FORM_NOT_EXIST_ID;
197 }
198 /**
199 * @brief Get record from DB cache with formId
200 * @param formId Form data Id
201 * @param record Form db data
202 * @return Returns ERR_OK on success, others on failure.
203 */
GetDBRecord(const int64_t formId,FormDBInfo & record) const204 ErrCode FormDbCache::GetDBRecord(const int64_t formId, FormDBInfo &record) const
205 {
206 std::lock_guard<std::mutex> lock(formDBInfosMutex_);
207 for (const FormDBInfo &dbInfo : formDBInfos_) {
208 if (dbInfo.formId == formId) {
209 record = dbInfo;
210 return ERR_OK;
211 }
212 }
213 HILOG_ERROR("%{public}s, not find formId[%{public}" PRId64 "]", __func__, formId);
214 return ERR_APPEXECFWK_FORM_NOT_EXIST_ID;
215 }
216 /**
217 * @brief Use record save or update DB data and DB cache with formId
218 * @param formId Form data Id
219 * @param record Form data
220 * @return Returns ERR_OK on success, others on failure.
221 */
UpdateDBRecord(const int64_t formId,const FormRecord & record) const222 ErrCode FormDbCache::UpdateDBRecord(const int64_t formId, const FormRecord &record) const
223 {
224 FormDBInfo formDBInfo(formId, record);
225 return FormDbCache::GetInstance().SaveFormInfo(formDBInfo);
226 }
227 /**
228 * @brief Get no host db record.
229 * @param uid The caller uid.
230 * @param noHostFormDBList no host db record list.
231 * @param foundFormsMap Form Id list.
232 * @return Returns ERR_OK on success, others on failure.
233 */
GetNoHostDBForms(const int uid,std::map<FormIdKey,std::set<int64_t>> & noHostFormDBList,std::map<int64_t,bool> & foundFormsMap)234 ErrCode FormDbCache::GetNoHostDBForms(const int uid, std::map<FormIdKey,
235 std::set<int64_t>> &noHostFormDBList, std::map<int64_t, bool> &foundFormsMap)
236 {
237 std::lock_guard<std::mutex> lock(formDBInfosMutex_);
238 for (FormDBInfo& dbInfo : formDBInfos_) {
239 if (dbInfo.Contains(uid)) {
240 dbInfo.Remove(uid);
241 if (dbInfo.formUserUids.empty()) {
242 FormIdKey formIdKey(dbInfo.bundleName, dbInfo.abilityName);
243 auto itIdsSet = noHostFormDBList.find(formIdKey);
244 if (itIdsSet == noHostFormDBList.end()) {
245 std::set<int64_t> formIdsSet;
246 formIdsSet.emplace(dbInfo.formId);
247 noHostFormDBList.emplace(formIdKey, formIdsSet);
248 } else {
249 itIdsSet->second.emplace(dbInfo.formId);
250 }
251 } else {
252 foundFormsMap.emplace(dbInfo.formId, false);
253 SaveFormInfoNolock(dbInfo);
254 FormBmsHelper::GetInstance().NotifyModuleNotRemovable(dbInfo.bundleName, dbInfo.moduleName);
255 }
256 }
257 }
258 return ERR_OK;
259 }
260 /**
261 * @brief Get match count by bundleName and moduleName.
262 * @param bundleName BundleName.
263 * @param moduleName ModuleName.
264 * @return Returns match count.
265 */
GetMatchCount(const std::string & bundleName,const std::string & moduleName)266 int FormDbCache::GetMatchCount(const std::string &bundleName, const std::string &moduleName)
267 {
268 int32_t matchCount {0};
269 std::vector<FormDBInfo> formDBInfos;
270 std::lock_guard<std::mutex> lock(formDBInfosMutex_);
271 for (FormDBInfo &dbInfo : formDBInfos_) {
272 if (dbInfo.bundleName == bundleName && dbInfo.moduleName == moduleName) {
273 ++matchCount;
274 }
275 }
276 return matchCount;
277 }
278 /**
279 * @brief delete forms bu userId.
280 *
281 * @param userId user ID.
282 */
DeleteDBFormsByUserId(const int32_t userId)283 void FormDbCache::DeleteDBFormsByUserId(const int32_t userId)
284 {
285 std::lock_guard<std::mutex> lock(formDBInfosMutex_);
286 std::vector<FormDBInfo>::iterator itRecord;
287 for (itRecord = formDBInfos_.begin(); itRecord != formDBInfos_.end();) {
288 if (userId == itRecord->userId) {
289 int64_t formId = itRecord->formId;
290 if (dataStorage_->DeleteStorageFormInfo(std::to_string(formId)) == ERR_OK) {
291 itRecord = formDBInfos_.erase(itRecord);
292 } else {
293 HILOG_ERROR("%{public}s, failed to delete form, formId[%{public}" PRId64 "]", __func__, formId);
294 itRecord++;
295 }
296 } else {
297 itRecord++;
298 }
299 }
300 }
GetDataStorage() const301 std::shared_ptr<FormStorageMgr> FormDbCache::GetDataStorage() const
302 {
303 return dataStorage_;
304 }
305
306 /**
307 * @brief handle get no host invalid DB forms.
308 * @param userId User ID.
309 * @param callingUid The UID of the proxy.
310 * @param matchedFormIds The set of the valid forms.
311 * @param noHostDBFormsMap The map of the no host forms.
312 * @param foundFormsMap The map of the found forms.
313 */
GetNoHostInvalidDBForms(int32_t userId,int32_t callingUid,std::set<int64_t> & matchedFormIds,std::map<FormIdKey,std::set<int64_t>> & noHostDBFormsMap,std::map<int64_t,bool> & foundFormsMap)314 void FormDbCache::GetNoHostInvalidDBForms(int32_t userId, int32_t callingUid, std::set<int64_t> &matchedFormIds,
315 std::map<FormIdKey, std::set<int64_t>> &noHostDBFormsMap,
316 std::map<int64_t, bool> &foundFormsMap)
317 {
318 std::lock_guard<std::mutex> lock(formDBInfosMutex_);
319 for (auto &formRecord: formDBInfos_) {
320 int64_t formId = formRecord.formId;
321
322 // check userID
323 if (userId != formRecord.userId) {
324 continue;
325 }
326 // check UID
327 auto iter = std::find(formRecord.formUserUids.begin(), formRecord.formUserUids.end(), callingUid);
328 if (iter == formRecord.formUserUids.end()) {
329 continue;
330 }
331 // check valid form set
332 if (matchedFormIds.find(formId) != matchedFormIds.end()) {
333 continue;
334 }
335
336 HILOG_DEBUG("found invalid form: %{public}" PRId64 "", formId);
337 formRecord.formUserUids.erase(iter);
338 if (formRecord.formUserUids.empty()) {
339 FormIdKey formIdKey(formRecord.bundleName, formRecord.abilityName);
340 auto itIdsSet = noHostDBFormsMap.find(formIdKey);
341 if (itIdsSet == noHostDBFormsMap.end()) {
342 std::set<int64_t> formIdsSet;
343 formIdsSet.emplace(formId);
344 noHostDBFormsMap.emplace(formIdKey, formIdsSet);
345 } else {
346 itIdsSet->second.emplace(formId);
347 }
348 } else {
349 foundFormsMap.emplace(formId, false);
350 SaveFormInfoNolock(formRecord);
351 FormBmsHelper::GetInstance().NotifyModuleNotRemovable(formRecord.bundleName, formRecord.moduleName);
352 }
353 }
354 }
355
356 /**
357 * @brief handle delete no host DB forms.
358 * @param callingUid The UID of the proxy.
359 * @param noHostFormDbMap The map of the no host forms.
360 * @param foundFormsMap The map of the found forms.
361 */
BatchDeleteNoHostDBForms(int32_t callingUid,std::map<FormIdKey,std::set<int64_t>> & noHostDBFormsMap,std::map<int64_t,bool> & foundFormsMap)362 void FormDbCache::BatchDeleteNoHostDBForms(int32_t callingUid, std::map<FormIdKey, std::set<int64_t>> &noHostDBFormsMap,
363 std::map<int64_t, bool> &foundFormsMap)
364 {
365 std::set<FormIdKey> removableModuleSet;
366 for (auto &element : noHostDBFormsMap) {
367 std::set<int64_t> &formIds = element.second;
368 FormIdKey formIdKey = element.first;
369 std::string bundleName = formIdKey.bundleName;
370 std::string abilityName = formIdKey.abilityName;
371 FormProviderMgr::GetInstance().NotifyProviderFormsBatchDelete(bundleName, abilityName, formIds);
372 for (const int64_t formId : formIds) {
373 foundFormsMap.emplace(formId, true);
374 FormDBInfo dbInfo;
375 int errCode = GetDBRecord(formId, dbInfo);
376 if (errCode == ERR_OK) {
377 FormIdKey removableModuleFormIdKey(dbInfo.bundleName, dbInfo.moduleName);
378 removableModuleSet.emplace(removableModuleFormIdKey);
379 DeleteFormInfo(formId);
380 }
381 FormDataMgr::GetInstance().DeleteFormRecord(formId);
382 }
383 }
384
385 for (const FormIdKey &item : removableModuleSet) {
386 int32_t matchCount = GetMatchCount(item.bundleName, item.moduleName);
387 if (matchCount == 0) {
388 FormBmsHelper::GetInstance().NotifyModuleRemovable(item.bundleName, item.moduleName);
389 }
390 }
391 }
392
393 /**
394 * @brief handle delete invalid DB forms.
395 * @param userId User ID.
396 * @param callingUid The UID of the proxy.
397 * @param matchedFormIds The set of the valid forms.
398 * @param removedFormsMap The map of the removed invalid forms.
399 * @return Returns ERR_OK on success, others on failure.
400 */
DeleteInvalidDBForms(int32_t userId,int32_t callingUid,std::set<int64_t> & matchedFormIds,std::map<int64_t,bool> & removedFormsMap)401 ErrCode FormDbCache::DeleteInvalidDBForms(int32_t userId, int32_t callingUid, std::set<int64_t> &matchedFormIds,
402 std::map<int64_t, bool> &removedFormsMap)
403 {
404 HILOG_INFO("DeleteInvalidDBForms start, userId = %{public}d, callingUid = %{public}d", userId, callingUid);
405 std::map<int64_t, bool> foundFormsMap {};
406 std::map<FormIdKey, std::set<int64_t>> noHostDBFormsMap {};
407
408 GetNoHostInvalidDBForms(userId, callingUid, matchedFormIds, noHostDBFormsMap, foundFormsMap);
409
410 if (!foundFormsMap.empty()) {
411 for (const auto &element : foundFormsMap) {
412 FormDataMgr::GetInstance().DeleteFormUserUid(element.first, callingUid);
413 }
414 }
415
416 BatchDeleteNoHostDBForms(callingUid, noHostDBFormsMap, foundFormsMap);
417 HILOG_DEBUG("foundFormsMap size: %{public}zu", foundFormsMap.size());
418 HILOG_DEBUG("noHostDBFormsMap size: %{public}zu", noHostDBFormsMap.size());
419
420 if (!foundFormsMap.empty()) {
421 removedFormsMap.insert(foundFormsMap.begin(), foundFormsMap.end());
422 }
423
424 HILOG_INFO("DeleteInvalidDBForms done");
425 return ERR_OK;
426 }
427 } // namespace AppExecFwk
428 } // namespace OHOS
429