1 /*
2 * Copyright (c) 2021-2022 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 "voicemail_ability.h"
17
18 #include <mutex>
19
20 #include "ability_loader.h"
21 #include "common.h"
22 #include "contacts_columns.h"
23 #include "contacts_common_event.h"
24 #include "contacts_datashare_stub_impl.h"
25 #include "datashare_ext_ability_context.h"
26 #include "datashare_predicates.h"
27 #include "file_utils.h"
28 #include "predicates_convert.h"
29 #include "rdb_predicates.h"
30 #include "rdb_utils.h"
31 #include "sql_analyzer.h"
32 #include "uri_utils.h"
33
34 namespace OHOS {
35 namespace AbilityRuntime {
36 namespace {
37 std::mutex g_mutex;
38 }
39 std::shared_ptr<Contacts::VoiceMailDataBase> VoiceMailAbility::voiceMailDataBase_ = nullptr;
40 std::map<std::string, int> VoiceMailAbility::uriValueMap_ = {
41 {"/com.ohos.voicemailability/calls/voicemail", Contacts::VOICEMAIL},
42 {"/com.ohos.voicemailability/calls/replaying", Contacts::REPLAYING}
43 };
44
Create()45 VoiceMailAbility* VoiceMailAbility::Create()
46 {
47 return new VoiceMailAbility();
48 }
49
VoiceMailAbility()50 VoiceMailAbility::VoiceMailAbility() : DataShareExtAbility()
51 {
52 }
53
~VoiceMailAbility()54 VoiceMailAbility::~VoiceMailAbility()
55 {
56 }
57
OnConnect(const AAFwk::Want & want)58 sptr<IRemoteObject> VoiceMailAbility::OnConnect(const AAFwk::Want &want)
59 {
60 HILOG_INFO("VoiceMailAbility %{public}s begin.", __func__);
61 Extension::OnConnect(want);
62 sptr<DataShare::ContactsDataShareStubImpl> remoteObject = new (std::nothrow) DataShare::ContactsDataShareStubImpl(
63 std::static_pointer_cast<VoiceMailAbility>(shared_from_this()));
64 if (remoteObject == nullptr) {
65 HILOG_ERROR("%{public}s No memory allocated for DataShareStubImpl", __func__);
66 return nullptr;
67 }
68 HILOG_INFO("VoiceMailAbility %{public}s end.", __func__);
69 return remoteObject->AsObject();
70 }
71
OnStart(const Want & want)72 void VoiceMailAbility::OnStart(const Want &want)
73 {
74 HILOG_INFO("VoiceMailAbility %{public}s begin.", __func__);
75 Extension::OnStart(want);
76 auto context = AbilityRuntime::Context::GetApplicationContext();
77 if (context != nullptr) {
78 std::string basePath = context->GetDatabaseDir();
79 Contacts::ContactsPath::RDB_PATH = basePath + "/";
80 Contacts::ContactsPath::RDB_BACKUP_PATH = basePath + "/backup/";
81 }
82 }
83
84 /**
85 * @brief VoiceMailAbility BeginTransaction emptiness problems
86 *
87 * @param code the return number of BeginTransaction
88 * @param mutex transmission parameter : lock
89 *
90 * @return BeginTransaction emptiness true or false
91 */
IsBeginTransactionOK(int code,std::mutex & mutex)92 bool VoiceMailAbility::IsBeginTransactionOK(int code, std::mutex &mutex)
93 {
94 mutex.try_lock();
95 if (code != 0) {
96 HILOG_ERROR("IsBeginTransactionOK fail");
97 mutex.unlock();
98 return false;
99 }
100 return true;
101 }
102
103 /**
104 * @brief VoiceMailAbility Commit emptiness problems
105 *
106 * @param code the return number of Commit
107 * @param mutex transmission parameter : lock
108 *
109 * @return Commit emptiness true or false
110 */
IsCommitOK(int code,std::mutex & mutex)111 bool VoiceMailAbility::IsCommitOK(int code, std::mutex &mutex)
112 {
113 mutex.try_lock();
114 if (code != 0) {
115 HILOG_ERROR("IsCommitOK fail");
116 mutex.unlock();
117 return false;
118 }
119 return true;
120 }
121
122 /**
123 * @brief VoiceMailAbility Insert database
124 *
125 * @param uri Determine the data table name based on the URI
126 * @param value Insert the data value of the database
127 *
128 * @return Insert database results code
129 */
Insert(const Uri & uri,const DataShare::DataShareValuesBucket & value)130 int VoiceMailAbility::Insert(const Uri &uri, const DataShare::DataShareValuesBucket &value)
131 {
132 OHOS::NativeRdb::ValuesBucket valuesBucket = RdbDataShareAdapter::RdbUtils::ToValuesBucket(value);
133 Contacts::SqlAnalyzer sqlAnalyzer;
134 bool isOk = sqlAnalyzer.CheckValuesBucket(valuesBucket);
135 if (!isOk) {
136 HILOG_ERROR("VoiceMailAbility CheckValuesBucket is error");
137 return Contacts::RDB_EXECUTE_FAIL;
138 }
139 g_mutex.lock();
140 voiceMailDataBase_ = Contacts::VoiceMailDataBase::GetInstance();
141 int rowRet = Contacts::RDB_EXECUTE_FAIL;
142 int ret = voiceMailDataBase_->BeginTransaction();
143 if (!IsBeginTransactionOK(ret, g_mutex)) {
144 g_mutex.unlock();
145 return Contacts::RDB_EXECUTE_FAIL;
146 }
147 rowRet = InsertExecute(uri, valuesBucket);
148 if (rowRet == Contacts::OPERATION_ERROR) {
149 voiceMailDataBase_->RollBack();
150 g_mutex.unlock();
151 return Contacts::OPERATION_ERROR;
152 }
153 ret = voiceMailDataBase_->Commit();
154 if (!IsCommitOK(ret, g_mutex)) {
155 voiceMailDataBase_->RollBack();
156 g_mutex.unlock();
157 return Contacts::RDB_EXECUTE_FAIL;
158 }
159 g_mutex.unlock();
160 DataBaseNotifyChange(Contacts::CONTACT_INSERT, uri);
161 return rowRet;
162 }
163
UriParse(Uri & uri)164 int VoiceMailAbility::UriParse(Uri &uri)
165 {
166 Contacts::UriUtils uriUtils;
167 int parseCode = uriUtils.UriParse(uri, uriValueMap_);
168 return parseCode;
169 }
170
InsertExecute(const OHOS::Uri & uri,const OHOS::NativeRdb::ValuesBucket & initialValues)171 int VoiceMailAbility::InsertExecute(const OHOS::Uri &uri, const OHOS::NativeRdb::ValuesBucket &initialValues)
172 {
173 int rowId = Contacts::RDB_EXECUTE_FAIL;
174 OHOS::Uri uriTemp = uri;
175 int code = UriParse(uriTemp);
176 switch (code) {
177 case Contacts::VOICEMAIL:
178 rowId = voiceMailDataBase_->InsertVoiceMail(Contacts::CallsTableName::VOICEMAIL, initialValues);
179 break;
180 case Contacts::REPLAYING:
181 rowId = voiceMailDataBase_->InsertVoiceMail(Contacts::CallsTableName::REPLYING, initialValues);
182 break;
183 default:
184 HILOG_ERROR("VoiceMailAbility ====>no match uri action");
185 break;
186 }
187 return rowId;
188 }
189
190 /**
191 * @brief VoiceMailAbility BatchInsert database
192 *
193 * @param uri Determine the data table name based on the URI
194 * @param value Insert the data values of the database
195 *
196 * @return BatchInsert database results code
197 */
BatchInsert(const Uri & uri,const std::vector<DataShare::DataShareValuesBucket> & values)198 int VoiceMailAbility::BatchInsert(const Uri &uri, const std::vector<DataShare::DataShareValuesBucket> &values)
199 {
200 unsigned int size = values.size();
201 if (size <= 0) {
202 return Contacts::RDB_EXECUTE_FAIL;
203 }
204 g_mutex.lock();
205 voiceMailDataBase_ = Contacts::VoiceMailDataBase::GetInstance();
206 int ret = voiceMailDataBase_->BeginTransaction();
207 if (!IsBeginTransactionOK(ret, g_mutex)) {
208 g_mutex.unlock();
209 return Contacts::RDB_EXECUTE_FAIL;
210 }
211 int count = 0;
212 for (unsigned int i = 0; i < size; i++) {
213 ++count;
214 DataShare::DataShareValuesBucket rawContactValues = values[i];
215 OHOS::NativeRdb::ValuesBucket value = RdbDataShareAdapter::RdbUtils::ToValuesBucket(rawContactValues);
216 int code = InsertExecute(uri, value);
217 if (code == Contacts::OPERATION_ERROR) {
218 voiceMailDataBase_->RollBack();
219 g_mutex.unlock();
220 return code;
221 }
222 if (count % Contacts::BATCH_INSERT_COUNT == 0) {
223 int markRet = voiceMailDataBase_->Commit();
224 int beginRet = voiceMailDataBase_->BeginTransaction();
225 if (!IsCommitOK(markRet, g_mutex) || !IsBeginTransactionOK(beginRet, g_mutex)) {
226 voiceMailDataBase_->RollBack();
227 g_mutex.unlock();
228 return Contacts::RDB_EXECUTE_FAIL;
229 }
230 }
231 }
232 int markRet = voiceMailDataBase_->Commit();
233 if (!IsCommitOK(markRet, g_mutex)) {
234 voiceMailDataBase_->RollBack();
235 g_mutex.unlock();
236 return Contacts::RDB_EXECUTE_FAIL;
237 }
238 g_mutex.unlock();
239 DataBaseNotifyChange(Contacts::CONTACT_INSERT, uri);
240 return Contacts::RDB_EXECUTE_OK;
241 }
242
243 /**
244 * @brief VoiceMailAbility Update database
245 *
246 * @param uri Determine the data table name based on the URI
247 * @param predicates Update the data value of the condition
248 *
249 * @return Update database results code
250 */
Update(const Uri & uri,const DataShare::DataSharePredicates & predicates,const DataShare::DataShareValuesBucket & value)251 int VoiceMailAbility::Update(
252 const Uri &uri, const DataShare::DataSharePredicates &predicates, const DataShare::DataShareValuesBucket &value)
253 {
254 OHOS::NativeRdb::ValuesBucket valuesBucket = RdbDataShareAdapter::RdbUtils::ToValuesBucket(value);
255 Contacts::SqlAnalyzer sqlAnalyzer;
256 bool isOk = sqlAnalyzer.CheckValuesBucket(valuesBucket);
257 if (!isOk) {
258 HILOG_ERROR("VoiceMailAbility CheckValuesBucket is error");
259 return Contacts::RDB_EXECUTE_FAIL;
260 }
261 g_mutex.lock();
262 voiceMailDataBase_ = Contacts::VoiceMailDataBase::GetInstance();
263 Contacts::PredicatesConvert predicatesConvert;
264 int ret = Contacts::RDB_EXECUTE_FAIL;
265 OHOS::Uri uriTemp = uri;
266 int code = UriParse(uriTemp);
267 DataShare::DataSharePredicates dataSharePredicates = predicates;
268 OHOS::NativeRdb::RdbPredicates rdbPredicates("");
269 switch (code) {
270 case Contacts::VOICEMAIL:
271 rdbPredicates =
272 predicatesConvert.ConvertPredicates(Contacts::CallsTableName::VOICEMAIL, dataSharePredicates);
273 ret = voiceMailDataBase_->UpdateVoiceMail(valuesBucket, rdbPredicates);
274 break;
275 case Contacts::REPLAYING:
276 rdbPredicates =
277 predicatesConvert.ConvertPredicates(Contacts::CallsTableName::REPLYING, dataSharePredicates);
278 ret = voiceMailDataBase_->UpdateVoiceMail(valuesBucket, rdbPredicates);
279 break;
280 default:
281 HILOG_ERROR("VoiceMailAbility ====>no match uri action");
282 break;
283 }
284 g_mutex.unlock();
285 DataBaseNotifyChange(Contacts::CONTACT_UPDATE, uri);
286 return ret;
287 }
288
289 /**
290 * @brief VoiceMailAbility Delete database
291 *
292 * @param uri Determine the data table name based on the URI
293 * @param predicates Delete the data values of the condition
294 *
295 * @return Delete database results code
296 */
Delete(const Uri & uri,const DataShare::DataSharePredicates & predicates)297 int VoiceMailAbility::Delete(const Uri &uri, const DataShare::DataSharePredicates &predicates)
298 {
299 g_mutex.lock();
300 voiceMailDataBase_ = Contacts::VoiceMailDataBase::GetInstance();
301 Contacts::PredicatesConvert predicatesConvert;
302 int ret = Contacts::RDB_EXECUTE_FAIL;
303 OHOS::Uri uriTemp = uri;
304 int parseCode = UriParse(uriTemp);
305 DataShare::DataSharePredicates dataSharePredicates = predicates;
306 OHOS::NativeRdb::RdbPredicates rdbPredicates("");
307 switch (parseCode) {
308 case Contacts::VOICEMAIL:
309 rdbPredicates =
310 predicatesConvert.ConvertPredicates(Contacts::CallsTableName::VOICEMAIL, dataSharePredicates);
311 ret = voiceMailDataBase_->DeleteVoiceMail(rdbPredicates);
312 break;
313 case Contacts::REPLAYING:
314 rdbPredicates =
315 predicatesConvert.ConvertPredicates(Contacts::CallsTableName::REPLYING, dataSharePredicates);
316 ret = voiceMailDataBase_->DeleteVoiceMail(rdbPredicates);
317 break;
318 default:
319 HILOG_ERROR("VoiceMailAbility ====>no match uri action");
320 break;
321 }
322 g_mutex.unlock();
323 DataBaseNotifyChange(Contacts::CONTACT_DELETE, uri);
324 return ret;
325 }
326
327 /**
328 * @brief VoiceMailAbility Query database
329 *
330 * @param uri Determine the data table name based on the URI
331 * @param columns Columns returned by query
332 * @param predicates Query the data values of the condition
333 *
334 * @return Query database results
335 */
Query(const Uri & uri,const DataShare::DataSharePredicates & predicates,std::vector<std::string> & columns)336 std::shared_ptr<DataShare::DataShareResultSet> VoiceMailAbility::Query(
337 const Uri &uri, const DataShare::DataSharePredicates &predicates, std::vector<std::string> &columns)
338 {
339 HILOG_ERROR("VoiceMailAbility ====>Query start");
340 voiceMailDataBase_ = Contacts::VoiceMailDataBase::GetInstance();
341 Contacts::PredicatesConvert predicatesConvert;
342 OHOS::Uri uriTemp = uri;
343 int parseCode = UriParse(uriTemp);
344 std::shared_ptr<OHOS::NativeRdb::AbsSharedResultSet> result;
345 DataShare::DataSharePredicates dataSharePredicates = predicates;
346 OHOS::NativeRdb::RdbPredicates rdbPredicates("");
347 std::vector<std::string> columnsTemp = columns;
348 bool isUriMatch = true;
349 switch (parseCode) {
350 case Contacts::VOICEMAIL:
351 rdbPredicates =
352 predicatesConvert.ConvertPredicates(Contacts::CallsTableName::VOICEMAIL, dataSharePredicates);
353 result = voiceMailDataBase_->Query(rdbPredicates, columnsTemp);
354 break;
355 case Contacts::REPLAYING:
356 rdbPredicates =
357 predicatesConvert.ConvertPredicates(Contacts::CallsTableName::REPLYING, dataSharePredicates);
358 result = voiceMailDataBase_->Query(rdbPredicates, columnsTemp);
359 break;
360 default:
361 isUriMatch = false;
362 HILOG_ERROR("VoiceMailAbility ====>no match uri action");
363 break;
364 }
365 if (!isUriMatch) {
366 return nullptr;
367 }
368 auto queryResultSet = RdbDataShareAdapter::RdbUtils::ToResultSetBridge(result);
369 std::shared_ptr<DataShare::DataShareResultSet> sharedPtrResult =
370 std::make_shared<DataShare::DataShareResultSet>(queryResultSet);
371 HILOG_ERROR("VoiceMailAbility ====>Query end");
372 return sharedPtrResult;
373 }
374
DataBaseNotifyChange(int code,Uri uri)375 void VoiceMailAbility::DataBaseNotifyChange(int code, Uri uri)
376 {
377 Contacts::ContactsCommonEvent::SendCallLogChange(code);
378 }
379 } // namespace AbilityRuntime
380 } // namespace OHOS
381