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