• 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 "vcard_manager.h"
17 
18 #include "telephony_errors.h"
19 #include "telephony_log_wrapper.h"
20 #include "vcard_constant.h"
21 #include "vcard_encoder.h"
22 #include "vcard_file_utils.h"
23 #include "vcard_rdb_helper.h"
24 #include "vcard_utils.h"
25 
26 namespace OHOS {
27 namespace Telephony {
VCardManager()28 VCardManager::VCardManager()
29 {
30     listener_ = std::make_shared<VCardManager::DecodeListener>();
31 }
32 
GetContacts()33 std::vector<std::shared_ptr<VCardContact>> &VCardManager::DecodeListener::GetContacts()
34 {
35     return contacts_;
36 }
37 
OnStarted()38 void VCardManager::DecodeListener::OnStarted()
39 {
40     contacts_.clear();
41 }
42 
OnEnded()43 void VCardManager::DecodeListener::OnEnded()
44 {
45     TELEPHONY_LOGI("OnEnded contact size %{public}d", static_cast<int32_t>(contacts_.size()));
46     VCardDecoder::Close();
47 }
48 
OnOneContactStarted()49 void VCardManager::DecodeListener::OnOneContactStarted()
50 {
51     currentContact_ = std::make_shared<VCardContact>();
52 }
53 
OnOneContactEnded()54 void VCardManager::DecodeListener::OnOneContactEnded()
55 {
56     TELEPHONY_LOGI("OnOneContactEnded index %{public}d", static_cast<int32_t>(contacts_.size()));
57     contacts_.push_back(currentContact_);
58     currentContact_ = nullptr;
59 }
60 
OnRawDataCreated(std::shared_ptr<VCardRawData> rawData)61 void VCardManager::DecodeListener::OnRawDataCreated(std::shared_ptr<VCardRawData> rawData)
62 {
63     if (rawData == nullptr || currentContact_ == nullptr) {
64         return;
65     }
66     int32_t errorCode = TELEPHONY_SUCCESS;
67     currentContact_->AddRawData(rawData, errorCode);
68 }
69 
ImportLock(const std::string & path,std::shared_ptr<DataShare::DataShareHelper> dataShareHelper,int32_t accountId)70 int32_t VCardManager::ImportLock(
71     const std::string &path, std::shared_ptr<DataShare::DataShareHelper> dataShareHelper, int32_t accountId)
72 {
73     std::lock_guard<std::mutex> lock(mutex_);
74     if (dataShareHelper == nullptr) {
75         TELEPHONY_LOGE("DataShareHelper is nullptr");
76         return TELEPHONY_ERR_LOCAL_PTR_NULL;
77     }
78     SetDataHelper(dataShareHelper);
79     int32_t errorCode = Import(path, accountId);
80     Release();
81     TELEPHONY_LOGI("ImportLock errorCode : %{public}d finish", errorCode);
82     return errorCode;
83 }
84 
Import(const std::string & path,int32_t accountId)85 int32_t VCardManager::Import(const std::string &path, int32_t accountId)
86 {
87     int32_t errorCode = TELEPHONY_SUCCESS;
88     Decode(path, errorCode);
89     if (errorCode != TELEPHONY_SUCCESS) {
90         TELEPHONY_LOGE("Failed to decode");
91         return errorCode;
92     }
93     BatchInsertContactDbAbility(accountId, errorCode);
94     if (errorCode != TELEPHONY_SUCCESS) {
95         TELEPHONY_LOGE("Failed to insert ability");
96         return errorCode;
97     }
98     TELEPHONY_LOGI("Import size %{public}d success", static_cast<int32_t>(listener_->GetContacts().size()));
99     return errorCode;
100 }
101 
Decode(const std::string & path,int32_t & errorCode)102 void VCardManager::Decode(const std::string &path, int32_t &errorCode)
103 {
104     std::shared_ptr<VCardDecoder> decoder = VCardDecoder::Create(path, errorCode);
105     if (decoder == nullptr || errorCode != TELEPHONY_SUCCESS) {
106         TELEPHONY_LOGE("Failed to get decoder");
107         return;
108     }
109     decoder->AddVCardDecodeListener(listener_);
110     decoder->Decode(errorCode);
111     if (errorCode != TELEPHONY_SUCCESS) {
112         TELEPHONY_LOGE("Failed to decode");
113     }
114 }
115 
InsertContactDbAbility(int32_t accountId,int32_t & errorCode)116 void VCardManager::InsertContactDbAbility(int32_t accountId, int32_t &errorCode)
117 {
118     if (listener_ == nullptr) {
119         errorCode = TELEPHONY_ERR_LOCAL_PTR_NULL;
120         return;
121     }
122     if (listener_->GetContacts().size() == 0) {
123         errorCode = TELEPHONY_ERR_VCARD_FILE_INVALID;
124         return;
125     }
126     for (std::shared_ptr<VCardContact> contact : listener_->GetContacts()) {
127         auto rawId = InsertRawContact(accountId, contact);
128         if (rawId <= 0) {
129             TELEPHONY_LOGE("Failed to insert raw contact");
130             errorCode = TELEPHONY_ERR_LOCAL_PTR_NULL;
131             continue;
132         }
133         if (InsertContactData(rawId, contact) == TELEPHONY_ERROR) {
134             TELEPHONY_LOGE("Insert contactData failed");
135             errorCode = TELEPHONY_ERR_LOCAL_PTR_NULL;
136         }
137     }
138 }
139 
BatchInsertContactDbAbility(int32_t accountId,int32_t & errorCode)140 void VCardManager::BatchInsertContactDbAbility(int32_t accountId, int32_t &errorCode)
141 {
142     if (listener_ == nullptr) {
143         errorCode = TELEPHONY_ERR_LOCAL_PTR_NULL;
144         return;
145     }
146     if (listener_->GetContacts().size() < BATCH_INSERT_MAX_SIZE) {
147         TELEPHONY_LOGI("contactData < BATCH_INSERT_MAX_SIZE");
148         InsertContactDbAbility(accountId, errorCode);
149         return;
150     }
151     if (listener_->GetContacts().size() == 0) {
152         errorCode = TELEPHONY_ERR_VCARD_FILE_INVALID;
153         return;
154     }
155     std::vector<std::vector<std::shared_ptr<VCardContact>>> splitList =
156         SplitContactsVector(listener_->GetContacts(), BATCH_INSERT_MAX_SIZE);
157     TELEPHONY_LOGI(
158         "contactData > BATCH_INSERT_MAX_SIZE, split List size %{public}d", static_cast<int32_t>(splitList.size()));
159     for (std::vector<std::shared_ptr<VCardContact>> list : splitList) {
160         TELEPHONY_LOGI("List size %{public}d", static_cast<int32_t>(list.size()));
161         std::vector<int32_t> rawIds;
162         BatchInsertRawContact(accountId, list.size(), rawIds, errorCode, list);
163         if (errorCode == TELEPHONY_ERROR) {
164             TELEPHONY_LOGE("Failed to batch insert raw contact");
165             continue;
166         }
167         BatchInsertContactData(rawIds, list, errorCode);
168         if (errorCode == TELEPHONY_ERROR) {
169             TELEPHONY_LOGE("Failed to batch insert contactData");
170             continue;
171         }
172     }
173 }
174 
BatchInsertRawContact(int32_t accountId,uint32_t size,std::vector<int32_t> & rawIds,int32_t & errorCode,const std::vector<std::shared_ptr<VCardContact>> & contactList)175 void VCardManager::BatchInsertRawContact(
176     int32_t accountId, uint32_t size, std::vector<int32_t> &rawIds, int32_t &errorCode,
177     const std::vector<std::shared_ptr<VCardContact>> &contactList)
178 {
179     int32_t rawContactMaxId = VCardRdbHelper::GetInstance().QueryRawContactMaxId(static_cast<int32_t>(size));
180     std::vector<DataShare::DataShareValuesBucket> rawContactValues;
181     for (uint32_t i = 0; i < size; i++) {
182         OHOS::DataShare::DataShareValuesBucket valuesBucket;
183         auto contact = contactList[i];
184         contact->BuildRawContactDataDisplayName(valuesBucket);
185         std::string uid = contact->GetUid();
186         if (!uid.empty()) {
187             valuesBucket.Put(RawContact::UUID, uid);
188         }
189         valuesBucket.Put(RawContact::ACCOUNT_ID, accountId);
190         int32_t newRawId = rawContactMaxId + static_cast<int32_t>(i) + 1;
191         valuesBucket.Put(RawContact::ID, newRawId);
192         rawContactValues.push_back(valuesBucket);
193         rawIds.push_back(newRawId);
194     }
195     VCardRdbHelper::GetInstance().BatchInsertRawContact(rawContactValues);
196 }
197 
BatchInsertContactData(std::vector<int32_t> & rawIds,const std::vector<std::shared_ptr<VCardContact>> & contactList,int32_t & errorCode)198 void VCardManager::BatchInsertContactData(
199     std::vector<int32_t> &rawIds, const std::vector<std::shared_ptr<VCardContact>> &contactList, int32_t &errorCode)
200 {
201     std::vector<DataShare::DataShareValuesBucket> contactDataValues;
202     for (size_t i = 0; i < rawIds.size(); i++) {
203         int32_t rawId = rawIds[i];
204         TELEPHONY_LOGI("rawId %{public}d", rawId);
205         std::shared_ptr<VCardContact> contact = contactList[i];
206         if (contact == nullptr) {
207             errorCode = TELEPHONY_ERROR;
208             TELEPHONY_LOGE("contact is nullptr");
209             continue;
210         }
211         contact->BuildContactData(rawId, contactDataValues);
212         if (contactDataValues.empty()) {
213             TELEPHONY_LOGE("no contactData insert");
214             errorCode = TELEPHONY_ERROR;
215         }
216     }
217     int ret = VCardRdbHelper::GetInstance().BatchInsertContactData(contactDataValues);
218     if (ret == TELEPHONY_ERROR) {
219         TELEPHONY_LOGE("batch insert contactDatat failed");
220         errorCode = TELEPHONY_ERROR;
221     }
222 }
223 
SplitContactsVector(std::vector<std::shared_ptr<VCardContact>> list,size_t step)224 std::vector<std::vector<std::shared_ptr<VCardContact>>> VCardManager::SplitContactsVector(
225     std::vector<std::shared_ptr<VCardContact>> list, size_t step)
226 {
227     std::vector<std::vector<std::shared_ptr<VCardContact>>> result;
228     if (step >= list.size()) {
229         result.push_back(list);
230     } else {
231         std::vector<std::shared_ptr<VCardContact>>::iterator curPtr = list.begin();
232         std::vector<std::shared_ptr<VCardContact>>::iterator endPtr = list.end();
233         std::vector<std::shared_ptr<VCardContact>>::iterator end;
234         while (curPtr < endPtr) {
235             end = static_cast<size_t>(endPtr - curPtr) > step ? (step + curPtr) : endPtr;
236             step = static_cast<size_t>(endPtr - curPtr) > step ? step : static_cast<size_t>(endPtr - curPtr);
237             result.push_back(std::vector<std::shared_ptr<VCardContact>>(curPtr, end));
238             curPtr += step;
239         }
240     }
241     return result;
242 }
243 
InsertRawContact(int32_t accountId,std::shared_ptr<VCardContact> contact)244 int32_t VCardManager::InsertRawContact(int32_t accountId, std::shared_ptr<VCardContact> contact)
245 {
246     OHOS::DataShare::DataShareValuesBucket valuesBucket;
247     valuesBucket.Put(RawContact::ACCOUNT_ID, accountId);
248     contact->BuildRawContactDataDisplayName(valuesBucket);
249     std::string uid = contact->GetUid();
250     if (!uid.empty()) {
251         valuesBucket.Put(RawContact::UUID, uid);
252     }
253     return VCardRdbHelper::GetInstance().InsertRawContact(valuesBucket);
254 }
255 
IsContactsIdExit(int32_t accountId)256 bool VCardManager::IsContactsIdExit(int32_t accountId)
257 {
258     std::vector<std::string> columns;
259     OHOS::DataShare::DataSharePredicates predicates;
260     predicates.EqualTo(Contact::ID, std::to_string(accountId));
261     auto resultSet = VCardRdbHelper::GetInstance().QueryContact(columns, predicates);
262     if (resultSet == nullptr) {
263         return false;
264     }
265     bool result = (resultSet->GoToFirstRow() == DataShare::E_OK);
266     resultSet->Close();
267     return result;
268 }
269 
IsAccountIdExit(int32_t accountId)270 bool VCardManager::IsAccountIdExit(int32_t accountId)
271 {
272     std::vector<std::string> columns;
273     OHOS::DataShare::DataSharePredicates predicates;
274     predicates.EqualTo(Account::ID, std::to_string(accountId));
275     auto resultSet = VCardRdbHelper::GetInstance().QueryAccount(columns, predicates);
276     if (resultSet == nullptr) {
277         return false;
278     }
279     bool result = (resultSet->GoToFirstRow() == DataShare::E_OK);
280     resultSet->Close();
281     return result;
282 }
283 
InsertContactData(int32_t rawId,std::shared_ptr<VCardContact> contact)284 int32_t VCardManager::InsertContactData(int32_t rawId, std::shared_ptr<VCardContact> contact)
285 {
286     if (contact == nullptr) {
287         return TELEPHONY_ERROR;
288     }
289     std::vector<DataShare::DataShareValuesBucket> contactDataValues;
290     contact->BuildContactData(rawId, contactDataValues);
291     if (contactDataValues.empty()) {
292         TELEPHONY_LOGI("no data insert");
293         return TELEPHONY_ERROR;
294     }
295     int ret = VCardRdbHelper::GetInstance().InsertContactData(contactDataValues);
296     if (ret == TELEPHONY_ERROR) {
297         TELEPHONY_LOGE("insert failed");
298         return TELEPHONY_ERROR;
299     }
300     return TELEPHONY_SUCCESS;
301 }
302 
ParameterTypeAndCharsetCheck(int32_t cardType,std::string charset,int32_t & errorCode)303 bool VCardManager::ParameterTypeAndCharsetCheck(int32_t cardType, std::string charset, int32_t &errorCode)
304 {
305     if (cardType < VERSION_21_NUM || cardType > VERSION_40_NUM) {
306         errorCode = TELEPHONY_ERR_ARGUMENT_INVALID;
307         return false;
308     }
309     if (!charset.empty() && !VCardUtils::EqualsIgnoreCase(DEFAULT_CHARSET, charset)) {
310         errorCode = TELEPHONY_ERR_ARGUMENT_INVALID;
311         return false;
312     }
313     errorCode = TELEPHONY_SUCCESS;
314     return true;
315 }
316 
ExportLock(std::string & path,std::shared_ptr<DataShare::DataShareHelper> dataShareHelper,const DataShare::DataSharePredicates & predicates,int32_t cardType,const std::string & charset)317 int32_t VCardManager::ExportLock(std::string &path, std::shared_ptr<DataShare::DataShareHelper> dataShareHelper,
318     const DataShare::DataSharePredicates &predicates, int32_t cardType, const std::string &charset)
319 {
320     std::lock_guard<std::mutex> lock(mutex_);
321     if (dataShareHelper == nullptr) {
322         TELEPHONY_LOGE("DataShareHelper is nullptr");
323         return TELEPHONY_ERR_LOCAL_PTR_NULL;
324     }
325     SetDataHelper(dataShareHelper);
326     int32_t errorCode = Export(path, predicates, cardType, charset);
327     Release();
328     TELEPHONY_LOGI("ExportLock errorCode : %{public}d finish", errorCode);
329     return errorCode;
330 }
331 
Export(std::string & path,const DataShare::DataSharePredicates & predicates,int32_t cardType,const std::string & charset)332 int32_t VCardManager::Export(
333     std::string &path, const DataShare::DataSharePredicates &predicates, int32_t cardType, const std::string &charset)
334 {
335     int32_t errorCode = TELEPHONY_SUCCESS;
336     if (!ParameterTypeAndCharsetCheck(cardType, charset, errorCode)) {
337         return errorCode;
338     }
339     std::vector<std::string> columns;
340     auto resultSet = VCardRdbHelper::GetInstance().QueryContact(columns, predicates);
341     if (resultSet == nullptr) {
342         TELEPHONY_LOGE("QueryContact failed");
343         return TELEPHONY_ERR_LOCAL_PTR_NULL;
344     }
345     std::string result = "";
346     result = ConstructVCardString(resultSet, cardType, charset, errorCode);
347     if (errorCode != TELEPHONY_SUCCESS) {
348         TELEPHONY_LOGE("Export data failed");
349         return errorCode;
350     }
351     if (path.empty()) {
352         std::string fileName = VCardUtils::CreateFileName();
353         path = VCARD_EXPORT_FILE_PATH + fileName;
354     } else {
355         path = path + VCardUtils::CreateFileName();
356     }
357     if (!result.empty()) {
358         VCardUtils::SaveFile(result, path);
359     } else {
360         return TELEPHONY_ERROR;
361     }
362     return TELEPHONY_SUCCESS;
363 }
364 
ExportToStr(std::string & str,const DataShare::DataSharePredicates & predicates,int32_t cardType,const std::string & charset)365 int32_t VCardManager::ExportToStr(
366     std::string &str, const DataShare::DataSharePredicates &predicates, int32_t cardType, const std::string &charset)
367 {
368     std::vector<std::string> columns;
369     auto resultSet = VCardRdbHelper::GetInstance().QueryContact(columns, predicates);
370     if (resultSet == nullptr) {
371         TELEPHONY_LOGE("QueryContact failed");
372         return TELEPHONY_ERR_LOCAL_PTR_NULL;
373     }
374     int32_t errorCode = TELEPHONY_SUCCESS;
375     str = ConstructVCardString(resultSet, cardType, charset, errorCode);
376     if (errorCode != TELEPHONY_SUCCESS) {
377         TELEPHONY_LOGE("Export data failed");
378         return errorCode;
379     }
380     return TELEPHONY_SUCCESS;
381 }
382 
ConstructVCardString(std::shared_ptr<DataShare::DataShareResultSet> & resultSet,int32_t cardType,const std::string & charset,int32_t & errorCode)383 std::string VCardManager::ConstructVCardString(
384     std::shared_ptr<DataShare::DataShareResultSet> &resultSet, int32_t cardType, const std::string &charset,
385     int32_t &errorCode)
386 {
387     int32_t resultSetNum = resultSet->GoToFirstRow();
388     if (resultSetNum != TELEPHONY_SUCCESS) {
389         errorCode = resultSetNum;
390         return "";
391     }
392     std::string result = "";
393     VCardEncoder encoder { cardType, charset };
394     int32_t contactCount = 0;
395     std::vector<int> contactIdList;
396     std::vector<std::vector<int>> contactIdLists;
397     while (resultSetNum == 0) {
398         int32_t index = 0;
399         int32_t contactId = 0;
400         resultSet->GetColumnIndex(Contact::ID, index);
401         resultSet->GetInt(index, contactId);
402         contactIdList.push_back(contactId);
403         resultSetNum = resultSet->GoToNextRow();
404         contactCount++;
405         if (contactCount % BATCH_INSERT_MAX_SIZE == 0) {
406             TELEPHONY_LOGI("pushBack contactid : %{public}d", contactId);
407             contactIdLists.push_back(contactIdList);
408             contactIdList.clear();
409         }
410     }
411     contactIdLists.push_back(contactIdList);
412     TELEPHONY_LOGI("before contstructVCard, contactIdList size : %{public}d", (int32_t)contactIdLists.size());
413     resultSet->Close();
414     result += encoder.ContructVCard(contactIdLists, errorCode);
415     return result;
416 }
417 
SetDataHelper(std::shared_ptr<DataShare::DataShareHelper> dataShareHelper)418 void VCardManager::SetDataHelper(std::shared_ptr<DataShare::DataShareHelper> dataShareHelper)
419 {
420     VCardRdbHelper::GetInstance().SetDataHelper(dataShareHelper);
421 }
422 
GetInstance()423 VCardManager &VCardManager::GetInstance()
424 {
425     static VCardManager instance;
426     return instance;
427 }
428 
Release()429 void VCardManager::Release()
430 {
431     VCardRdbHelper::GetInstance().Release();
432     if (listener_ != nullptr) {
433         listener_->GetContacts().clear();
434     }
435 }
436 } // namespace Telephony
437 } // namespace OHOS
438