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