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 "common.h"
21 #include "contacts_columns.h"
22 #include "contacts_common_event.h"
23 #include "contacts_datashare_stub_impl.h"
24 #include "datashare_ext_ability_context.h"
25 #include "datashare_predicates.h"
26 #include "file_utils.h"
27 #include "predicates_convert.h"
28 #include "rdb_predicates.h"
29 #include "rdb_utils.h"
30 #include "sql_analyzer.h"
31 #include "uri_utils.h"
32
33 namespace OHOS {
34 namespace AbilityRuntime {
35 namespace {
36 std::mutex g_mutex;
37 }
38 std::shared_ptr<Contacts::VoiceMailDataBase> VoiceMailAbility::voiceMailDataBase_ = nullptr;
39 std::map<std::string, int> VoiceMailAbility::uriValueMap_ = {
40 {"/com.ohos.voicemailability/calls/voicemail", Contacts::VOICEMAIL},
41 {"/com.ohos.voicemailability/calls/replaying", Contacts::REPLAYING}
42 };
43
Create()44 VoiceMailAbility* VoiceMailAbility::Create()
45 {
46 return new VoiceMailAbility();
47 }
48
VoiceMailAbility()49 VoiceMailAbility::VoiceMailAbility() : DataShareExtAbility()
50 {
51 }
52
~VoiceMailAbility()53 VoiceMailAbility::~VoiceMailAbility()
54 {
55 }
56
OnConnect(const AAFwk::Want & want)57 sptr<IRemoteObject> VoiceMailAbility::OnConnect(const AAFwk::Want &want)
58 {
59 HILOG_INFO("VoiceMailAbility %{public}s begin.", __func__);
60 Extension::OnConnect(want);
61 sptr<DataShare::ContactsDataShareStubImpl> remoteObject =
62 new (std::nothrow) DataShare::ContactsDataShareStubImpl();
63 if (remoteObject == nullptr) {
64 HILOG_ERROR("%{public}s No memory allocated for DataShareStubImpl", __func__);
65 return nullptr;
66 }
67 remoteObject->SetVoiceMailAbility(std::static_pointer_cast<VoiceMailAbility>(shared_from_this()));
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 if (!Telephony::TelephonyPermission::CheckPermission(Telephony::Permission::OHOS_PERMISSION_MANAGE_VOICEMAIL)) {
133 HILOG_ERROR("Permission denied!");
134 return Contacts::RDB_PERMISSION_ERROR;
135 }
136 OHOS::NativeRdb::ValuesBucket valuesBucket = RdbDataShareAdapter::RdbUtils::ToValuesBucket(value);
137 Contacts::SqlAnalyzer sqlAnalyzer;
138 bool isOk = sqlAnalyzer.CheckValuesBucket(valuesBucket);
139 if (!isOk) {
140 HILOG_ERROR("VoiceMailAbility CheckValuesBucket is error");
141 return Contacts::RDB_EXECUTE_FAIL;
142 }
143 g_mutex.lock();
144 voiceMailDataBase_ = Contacts::VoiceMailDataBase::GetInstance();
145 int ret = voiceMailDataBase_->BeginTransaction();
146 if (!IsBeginTransactionOK(ret, g_mutex)) {
147 g_mutex.unlock();
148 return Contacts::RDB_EXECUTE_FAIL;
149 }
150 int rowRet = InsertExecute(uri, valuesBucket);
151 if (rowRet == Contacts::OPERATION_ERROR) {
152 voiceMailDataBase_->RollBack();
153 g_mutex.unlock();
154 return Contacts::OPERATION_ERROR;
155 }
156 ret = voiceMailDataBase_->Commit();
157 if (!IsCommitOK(ret, g_mutex)) {
158 voiceMailDataBase_->RollBack();
159 g_mutex.unlock();
160 return Contacts::RDB_EXECUTE_FAIL;
161 }
162 g_mutex.unlock();
163 DataBaseNotifyChange(Contacts::CONTACT_INSERT, uri);
164 return rowRet;
165 }
166
UriParse(Uri & uri)167 int VoiceMailAbility::UriParse(Uri &uri)
168 {
169 Contacts::UriUtils uriUtils;
170 int parseCode = uriUtils.UriParse(uri, uriValueMap_);
171 return parseCode;
172 }
173
InsertExecute(const OHOS::Uri & uri,const OHOS::NativeRdb::ValuesBucket & initialValues)174 int VoiceMailAbility::InsertExecute(const OHOS::Uri &uri, const OHOS::NativeRdb::ValuesBucket &initialValues)
175 {
176 int rowId = Contacts::RDB_EXECUTE_FAIL;
177 OHOS::Uri uriTemp = uri;
178 int code = UriParse(uriTemp);
179 switch (code) {
180 case Contacts::VOICEMAIL:
181 rowId = voiceMailDataBase_->InsertVoiceMail(Contacts::CallsTableName::VOICEMAIL, initialValues);
182 break;
183 case Contacts::REPLAYING:
184 rowId = voiceMailDataBase_->InsertVoiceMail(Contacts::CallsTableName::REPLYING, initialValues);
185 break;
186 default:
187 HILOG_ERROR("VoiceMailAbility ====>no match uri action");
188 break;
189 }
190 return rowId;
191 }
192
193 /**
194 * @brief VoiceMailAbility BatchInsert database
195 *
196 * @param uri Determine the data table name based on the URI
197 * @param value Insert the data values of the database
198 *
199 * @return BatchInsert database results code
200 */
BatchInsert(const Uri & uri,const std::vector<DataShare::DataShareValuesBucket> & values)201 int VoiceMailAbility::BatchInsert(const Uri &uri, const std::vector<DataShare::DataShareValuesBucket> &values)
202 {
203 if (!Telephony::TelephonyPermission::CheckPermission(Telephony::Permission::OHOS_PERMISSION_MANAGE_VOICEMAIL)) {
204 HILOG_ERROR("Permission denied!");
205 return Contacts::RDB_PERMISSION_ERROR;
206 }
207 unsigned int size = values.size();
208 if (size < 1) {
209 return Contacts::RDB_EXECUTE_FAIL;
210 }
211 g_mutex.lock();
212 voiceMailDataBase_ = Contacts::VoiceMailDataBase::GetInstance();
213 int ret = voiceMailDataBase_->BeginTransaction();
214 if (!IsBeginTransactionOK(ret, g_mutex)) {
215 g_mutex.unlock();
216 return Contacts::RDB_EXECUTE_FAIL;
217 }
218 int count = 0;
219 for (unsigned int i = 0; i < size; i++) {
220 ++count;
221 DataShare::DataShareValuesBucket rawContactValues = values[i];
222 OHOS::NativeRdb::ValuesBucket value = RdbDataShareAdapter::RdbUtils::ToValuesBucket(rawContactValues);
223 int code = InsertExecute(uri, value);
224 if (code == Contacts::OPERATION_ERROR) {
225 voiceMailDataBase_->RollBack();
226 g_mutex.unlock();
227 return code;
228 }
229 if (count % Contacts::BATCH_INSERT_COUNT == 0) {
230 int markRet = voiceMailDataBase_->Commit();
231 int beginRet = voiceMailDataBase_->BeginTransaction();
232 if (!IsCommitOK(markRet, g_mutex) || !IsBeginTransactionOK(beginRet, g_mutex)) {
233 voiceMailDataBase_->RollBack();
234 g_mutex.unlock();
235 return Contacts::RDB_EXECUTE_FAIL;
236 }
237 }
238 }
239 int markRet = voiceMailDataBase_->Commit();
240 if (!IsCommitOK(markRet, g_mutex)) {
241 voiceMailDataBase_->RollBack();
242 g_mutex.unlock();
243 return Contacts::RDB_EXECUTE_FAIL;
244 }
245 g_mutex.unlock();
246 DataBaseNotifyChange(Contacts::CONTACT_INSERT, uri);
247 return Contacts::RDB_EXECUTE_OK;
248 }
249
250 /**
251 * @brief VoiceMailAbility Update database
252 *
253 * @param uri Determine the data table name based on the URI
254 * @param predicates Update the data value of the condition
255 *
256 * @return Update database results code
257 */
Update(const Uri & uri,const DataShare::DataSharePredicates & predicates,const DataShare::DataShareValuesBucket & value)258 int VoiceMailAbility::Update(
259 const Uri &uri, const DataShare::DataSharePredicates &predicates, const DataShare::DataShareValuesBucket &value)
260 {
261 if (!Telephony::TelephonyPermission::CheckPermission(Telephony::Permission::OHOS_PERMISSION_MANAGE_VOICEMAIL)) {
262 HILOG_ERROR("Permission denied!");
263 return Contacts::RDB_PERMISSION_ERROR;
264 }
265 OHOS::NativeRdb::ValuesBucket valuesBucket = RdbDataShareAdapter::RdbUtils::ToValuesBucket(value);
266 Contacts::SqlAnalyzer sqlAnalyzer;
267 bool isOk = sqlAnalyzer.CheckValuesBucket(valuesBucket);
268 if (!isOk) {
269 HILOG_ERROR("VoiceMailAbility CheckValuesBucket is error");
270 return Contacts::RDB_EXECUTE_FAIL;
271 }
272 g_mutex.lock();
273 voiceMailDataBase_ = Contacts::VoiceMailDataBase::GetInstance();
274 Contacts::PredicatesConvert predicatesConvert;
275 int ret = Contacts::RDB_EXECUTE_FAIL;
276 OHOS::Uri uriTemp = uri;
277 int code = UriParse(uriTemp);
278 DataShare::DataSharePredicates dataSharePredicates = predicates;
279 OHOS::NativeRdb::RdbPredicates rdbPredicates("");
280 switch (code) {
281 case Contacts::VOICEMAIL:
282 rdbPredicates =
283 predicatesConvert.ConvertPredicates(Contacts::CallsTableName::VOICEMAIL, dataSharePredicates);
284 ret = voiceMailDataBase_->UpdateVoiceMail(valuesBucket, rdbPredicates);
285 break;
286 case Contacts::REPLAYING:
287 rdbPredicates =
288 predicatesConvert.ConvertPredicates(Contacts::CallsTableName::REPLYING, dataSharePredicates);
289 ret = voiceMailDataBase_->UpdateVoiceMail(valuesBucket, rdbPredicates);
290 break;
291 default:
292 HILOG_ERROR("VoiceMailAbility ====>no match uri action");
293 break;
294 }
295 g_mutex.unlock();
296 DataBaseNotifyChange(Contacts::CONTACT_UPDATE, uri);
297 return ret;
298 }
299
300 /**
301 * @brief VoiceMailAbility Delete database
302 *
303 * @param uri Determine the data table name based on the URI
304 * @param predicates Delete the data values of the condition
305 *
306 * @return Delete database results code
307 */
Delete(const Uri & uri,const DataShare::DataSharePredicates & predicates)308 int VoiceMailAbility::Delete(const Uri &uri, const DataShare::DataSharePredicates &predicates)
309 {
310 if (!Telephony::TelephonyPermission::CheckPermission(Telephony::Permission::OHOS_PERMISSION_MANAGE_VOICEMAIL)) {
311 HILOG_ERROR("Permission denied!");
312 return Contacts::RDB_PERMISSION_ERROR;
313 }
314 g_mutex.lock();
315 voiceMailDataBase_ = Contacts::VoiceMailDataBase::GetInstance();
316 Contacts::PredicatesConvert predicatesConvert;
317 int ret = Contacts::RDB_EXECUTE_FAIL;
318 OHOS::Uri uriTemp = uri;
319 int parseCode = UriParse(uriTemp);
320 DataShare::DataSharePredicates dataSharePredicates = predicates;
321 OHOS::NativeRdb::RdbPredicates rdbPredicates("");
322 switch (parseCode) {
323 case Contacts::VOICEMAIL:
324 rdbPredicates =
325 predicatesConvert.ConvertPredicates(Contacts::CallsTableName::VOICEMAIL, dataSharePredicates);
326 ret = voiceMailDataBase_->DeleteVoiceMail(rdbPredicates);
327 break;
328 case Contacts::REPLAYING:
329 rdbPredicates =
330 predicatesConvert.ConvertPredicates(Contacts::CallsTableName::REPLYING, dataSharePredicates);
331 ret = voiceMailDataBase_->DeleteVoiceMail(rdbPredicates);
332 break;
333 default:
334 HILOG_ERROR("VoiceMailAbility ====>no match uri action");
335 break;
336 }
337 g_mutex.unlock();
338 DataBaseNotifyChange(Contacts::CONTACT_DELETE, uri);
339 return ret;
340 }
341
342 /**
343 * @brief VoiceMailAbility Query database
344 *
345 * @param uri Determine the data table name based on the URI
346 * @param columns Columns returned by query
347 * @param predicates Query the data values of the condition
348 *
349 * @return Query database results
350 */
Query(const Uri & uri,const DataShare::DataSharePredicates & predicates,std::vector<std::string> & columns,DataShare::DatashareBusinessError & businessError)351 std::shared_ptr<DataShare::DataShareResultSet> VoiceMailAbility::Query(const Uri &uri,
352 const DataShare::DataSharePredicates &predicates, std::vector<std::string> &columns,
353 DataShare::DatashareBusinessError &businessError)
354 {
355 if (!Telephony::TelephonyPermission::CheckPermission(Telephony::Permission::OHOS_PERMISSION_MANAGE_VOICEMAIL)) {
356 HILOG_ERROR("Permission denied!");
357 return nullptr;
358 }
359 HILOG_ERROR("VoiceMailAbility ====>Query start");
360 voiceMailDataBase_ = Contacts::VoiceMailDataBase::GetInstance();
361 Contacts::PredicatesConvert predicatesConvert;
362 OHOS::Uri uriTemp = uri;
363 int parseCode = UriParse(uriTemp);
364 std::shared_ptr<OHOS::NativeRdb::ResultSet> result;
365 DataShare::DataSharePredicates dataSharePredicates = predicates;
366 OHOS::NativeRdb::RdbPredicates rdbPredicates("");
367 std::vector<std::string> columnsTemp = columns;
368 bool isUriMatch = true;
369 switch (parseCode) {
370 case Contacts::VOICEMAIL:
371 rdbPredicates =
372 predicatesConvert.ConvertPredicates(Contacts::CallsTableName::VOICEMAIL, dataSharePredicates);
373 result = voiceMailDataBase_->Query(rdbPredicates, columnsTemp);
374 break;
375 case Contacts::REPLAYING:
376 rdbPredicates =
377 predicatesConvert.ConvertPredicates(Contacts::CallsTableName::REPLYING, dataSharePredicates);
378 result = voiceMailDataBase_->Query(rdbPredicates, columnsTemp);
379 break;
380 default:
381 isUriMatch = false;
382 HILOG_ERROR("VoiceMailAbility ====>no match uri action");
383 break;
384 }
385 if (!isUriMatch) {
386 return nullptr;
387 }
388 if (result == nullptr) {
389 HILOG_ERROR("AbsSharedResultSet is nullptr");
390 return nullptr;
391 }
392 auto queryResultSet = RdbDataShareAdapter::RdbUtils::ToResultSetBridge(result);
393 std::shared_ptr<DataShare::DataShareResultSet> sharedPtrResult =
394 std::make_shared<DataShare::DataShareResultSet>(queryResultSet);
395 HILOG_ERROR("VoiceMailAbility ====>Query end");
396 return sharedPtrResult;
397 }
398
DataBaseNotifyChange(int code,Uri uri)399 void VoiceMailAbility::DataBaseNotifyChange(int code, Uri uri)
400 {
401 Contacts::ContactsCommonEvent::SendCallLogChange(code);
402 }
403 } // namespace AbilityRuntime
404 } // namespace OHOS
405